我正在嘗試使用自定義排序功能對資料進行排序。不幸的是,該功能僅在記錄是大寫字母或小寫字母時才對專案進行排序。它不能正確地對混合大小寫字母的資料進行排序。這是實時鏈接
這是代碼
const useSortableData = (items, config = null) => {
const [sortConfig, setSortConfig] = React.useState(config);
const sortedItems = React.useMemo(() => {
let sortableItems = [...items];
if (sortConfig !== null) {
sortableItems.sort((a, b) => {
if (a[sortConfig.key] < b[sortConfig.key]) {
return sortConfig.direction === 'ascending' ? -1 : 1;
}
if (a[sortConfig.key] > b[sortConfig.key]) {
return sortConfig.direction === 'ascending' ? 1 : -1;
}
return 0;
});
}
return sortableItems;
}, [items, sortConfig]);
const requestSort = (key) => {
let direction = 'ascending';
if (
sortConfig &&
sortConfig.key === key &&
sortConfig.direction === 'ascending'
) {
direction = 'descending';
}
setSortConfig({ key, direction });
};
return { items: sortedItems, requestSort, sortConfig };
};
const ProductTable = (props) => {
const { items, requestSort, sortConfig } = useSortableData(props.products);
const getClassNamesFor = (name) => {
if (!sortConfig) {
return;
}
return sortConfig.key === name ? sortConfig.direction : undefined;
};
return (
<table>
<caption>Products</caption>
<thead>
<tr>
<th>
<button
type="button"
onClick={() => requestSort('name')}
className={getClassNamesFor('name')}
>
Name
</button>
</th>
<th>
<button
type="button"
onClick={() => requestSort('price')}
className={getClassNamesFor('price')}
>
Price
</button>
</th>
<th>
<button
type="button"
onClick={() => requestSort('stock')}
className={getClassNamesFor('stock')}
>
In Stock
</button>
</th>
</tr>
</thead>
<tbody>
{items.map((item) => (
<tr key={item.id}>
<td>{item.name}</td>
<td>${item.price}</td>
<td>{item.stock}</td>
</tr>
))}
</tbody>
</table>
);
};
function App() {
return (
<div className="App">
<ProductTable
products={[
{ id: 1, name: 'Cheese', price: 4.9, stock: 20 },
{ id: 2, name: 'milk', price: 1.9, stock: 32 },
{ id: 3, name: 'Yoghurt', price: 2.4, stock: 12 },
{ id: 4, name: 'Heavy Cream', price: 3.9, stock: 9 },
{ id: 5, name: 'butter', price: 0.9, stock: 99 },
{ id: 6, name: 'Sour Cream ', price: 2.9, stock: 86 },
{ id: 7, name: 'Fancy French Cheese ????', price: 99, stock: 12 },
]}
/>
</div>
);
}
ReactDOM.createRoot(document.querySelector("#root")).render(<App />);
body {
font-family: 'open sans', sans-serif;
font-size: 16px;
}
table {
width: 100%;
border-collapse: collapse;
}
thead th {
text-align: left;
border-bottom: 2px solid black;
}
thead button {
border: 0;
border-radius: none;
font-family: inherit;
font-weight: 700;
font-size: inherit;
padding: 0.5em;
margin-bottom: 1px;
}
thead button.ascending::after {
content: '??';
display: inline-block;
margin-left: 1em;
}
thead button.descending::after {
content: '??';
display: inline-block;
margin-left: 1em;
}
tbody td {
padding: 0.5em;
border-bottom: 1px solid #ccc;
}
tbody tr:hover {
background-color: #eee;
}
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>
我試圖將a和b從useSortable更改為小寫,但由于價格列帶有數字,因此出現錯誤。
無論區分大小寫,我該怎么做才能使其正常作業。
uj5u.com熱心網友回復:
我認為對不同的型別有不同的排序功能是合理的。我建議對字串型別和數字型別使用排序功能,并根據列型別使用它。這樣代碼變得更清晰和更易于維護。
uj5u.com熱心網友回復:
比較 2 個字串 usinga[sortConfig.key] < b[sortConfig.key]將導致基于字符代碼點而不是字符內容進行比較。根據內容比較 2 個字串的一種簡單方法是使用localeCompare().
如果您對此持肯定態度,a[sortConfig.key]并且b[sortConfig.key]將始終回傳一個字串,則return a[sortConfig.key].localeCompare(b[sortConfig.key])無需任何額外檢查即可。
但是,在您的場景中,它們也可以表示priceor stockwhich 是數字,因此沒有方法localeCompare()。所以我們應該事先檢查兩個值是否都是字串。
我個人不喜歡型別檢查,因為 JavaScript 是一種鴨式語言。我通常會檢查我需要的方法是否可用。
假設定義了以下幫助程式:
function hasMethod(item, methodName) {
// intentional != usage, checks for both null and undefined
return item != null && typeof item[methodName] === "function";
}
您可以按以下方式對集合進行排序:
const modifier = sortConfig.direction === 'ascending' ? 1 : -1;
sortableItems.sort((a, b) => {
const [valueA, valueB] = [a, b].map(item => item[sortConfig.key]);
const areLocaleComparable = [valueA, valueB].every(value => hasMethod(value, "localeCompare"));
if (areLocaleComparable) return valueA.localeCompare(valueB) * modifier;
return (-(valueA < valueB) || (valueA > valueB)) * modifier;
// or instead of the above line
if (valueA < valueB) return -1 * modifier;
if (valueA > valueB) return 1 * modifier;
return 0;
});
或者,如果您更愿意使用型別檢查,則可以使用typeof value === "string"而不是。hasMethod(value, "localeCompare")
uj5u.com熱心網友回復:
您可以檢查型別,例如:
if (typeof a[sortConfig.key] === "string" && typeof b[sortConfig.key] === "string") {
if (a[sortConfig.key].toLowerCase() < b[sortConfig.key].toLowerCase()) {
return sortConfig.direction === 'ascending' ? -1 : 1;
}
} else {
if (a[sortConfig.key] < b[sortConfig.key]) {
return sortConfig.direction === 'ascending' ? -1 : 1;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/514766.html
下一篇:無法對偶數后跟奇數的陣列進行排序
