可扩展 table 排序方法
Scalable table sorting approach
我想对 React 中的每一列进行排序。我可以做到,但是强制代码,例如,如果我有这个数组并将其显示在 html table 中,我希望当我单击 id 时它按升序排序,当我单击它时命名它按升序排序,再次单击时按降序排序,我希望姓名和年龄相同。同时我想要一个箭头,如果该列在 ascendig 中,则向上看,否则向下看。
const USERS = [
{ id: 1, name: "Andy", age: 32 },
{ id: 2, name: "Bob", age: 30 },
{ id: 3, name: "Tom Hulk", age: 40 },
{ id: 4, name: "Tom Hank", age: 50 },
{ id: 5, name: "Audra", age: 30 },
{ id: 6, name: "Anna", age: 68 },
{ id: 7, name: "Tom", age: 34 },
{ id: 8, name: "Tom Riddle", age: 28 },
{ id: 9, name: "Bolo", age: 23 },
];
我的方法是这样的,但是很丑也不实用。而且,当我更改箭头的排序状态时,它会更新所有箭头而不是我单击的列的箭头
const sortBy = (k) => {
if (k === "id") {
if (sort) {
const res = USERS.sort((a, b) => (a.id > b.id ? 1 : -1));
setDataFilter(res);
setSort(!sort);
console.log(res);
} else {
const res = USERS.sort((a, b) => (a.id < b.id ? 1 : -1));
setDataFilter(res);
setSort(!sort);
console.log(res);
}
} else if (k === "age") {
if (sort) {
const res = USERS.sort((a, b) => (a.age > b.age ? 1 : -1));
setDataFilter(res);
setSort(!sort);
console.log(res);
} else {
const res = USERS.sort((a, b) => (a.age < b.agek ? 1 : -1));
setDataFilter(res);
setSort(!sort);
console.log(res);
}
} else if (k === "name") {
if (sort) {
const res = USERS.sort((a, b) => a.name.localeCompare(b.name));
setDataFilter(res);
setSort(!sort);
console.log(res);
} else {
const res = USERS.sort((a, b) => b.name.localeCompare(a.name));
setDataFilter(res);
setSort(!sort);
console.log(res);
}
} else {
console.log("hmm");
}
};
您可能希望在映射对象中对回调进行排序(按 属性 名称或 属性 类型)。
此外,不要忘记利用 useMemo()
/ useCallback()
钩子通过记忆排序输出来提高排序性能(这可能对大量项目有益):
const users = [
{ id: 1, name: "Andy", age: 32 },
{ id: 2, name: "Bob", age: 30 },
{ id: 3, name: "Tom Hulk", age: 40 },
{ id: 4, name: "Tom Hank", age: 50 },
{ id: 5, name: "Audra", age: 30 },
{ id: 6, name: "Anna", age: 68 },
{ id: 7, name: "Tom", age: 34 },
{ id: 8, name: "Tom Riddle", age: 28 },
{ id: 9, name: "Bolo", age: 23 },
],
sortDirection = {
'asc': 1,
'desc': -1
},
numericSorter = propName =>
sortOrder =>
({[propName]:a}, {[propName]:b}) =>
(a-b)*sortDirection[sortOrder],
stringicSorter = propName =>
sortOrder =>
({[propName]:a}, {[propName]:b}) =>
a.localeCompare(b)*sortDirection[sortOrder],
sortMap = {
id: numericSorter('id'),
name: stringicSorter('name'),
age: numericSorter('age')
},
sortUsers = (users, byProp, sortOrder) =>
users.sort(sortMap[byProp](sortOrder))
console.log(sortUsers(users, 'name', 'desc'))
console.log(sortUsers(users, 'age', 'asc'))
.as-console-wrapper{min-height: 100%;}
试试下面的代码。它检查排序键值的类型并相应地选择排序方法。我重新使用了您的逻辑,使您的操作变得简单。
const USERS = [
{ id: 1, name: "Andy", age: 32 },
{ id: 2, name: "Bob", age: 30 },
{ id: 3, name: "Tom Hulk", age: 40 },
{ id: 4, name: "Tom Hank", age: 50 },
{ id: 5, name: "Audra", age: 30 },
{ id: 6, name: "Anna", age: 68 },
{ id: 7, name: "Tom", age: 34 },
{ id: 8, name: "Tom Riddle", age: 28 },
{ id: 9, name: "Bolo", age: 23 },
];
const sortBy = (k, sort) => {
var res;
if( USERS[0] && (typeof USERS[0][k] == 'string')) {
res = sort ? USERS.sort((a, b) => a[k].localeCompare(b[k])) : USERS.sort((a, b) => b[k].localeCompare(a[k]));
} else {
const f = sort ? 1 : -1;
res = USERS.sort((a, b) => (a[k] > b[k] ? f : -f));
}
// setDataFilter(res);
// setSort(!sort);
console.log(res);
}
sortBy('name', 1);
sortBy('age', 1);
sortBy('name', 0);
sortBy('age', 0);
我想对 React 中的每一列进行排序。我可以做到,但是强制代码,例如,如果我有这个数组并将其显示在 html table 中,我希望当我单击 id 时它按升序排序,当我单击它时命名它按升序排序,再次单击时按降序排序,我希望姓名和年龄相同。同时我想要一个箭头,如果该列在 ascendig 中,则向上看,否则向下看。
const USERS = [
{ id: 1, name: "Andy", age: 32 },
{ id: 2, name: "Bob", age: 30 },
{ id: 3, name: "Tom Hulk", age: 40 },
{ id: 4, name: "Tom Hank", age: 50 },
{ id: 5, name: "Audra", age: 30 },
{ id: 6, name: "Anna", age: 68 },
{ id: 7, name: "Tom", age: 34 },
{ id: 8, name: "Tom Riddle", age: 28 },
{ id: 9, name: "Bolo", age: 23 },
];
我的方法是这样的,但是很丑也不实用。而且,当我更改箭头的排序状态时,它会更新所有箭头而不是我单击的列的箭头
const sortBy = (k) => {
if (k === "id") {
if (sort) {
const res = USERS.sort((a, b) => (a.id > b.id ? 1 : -1));
setDataFilter(res);
setSort(!sort);
console.log(res);
} else {
const res = USERS.sort((a, b) => (a.id < b.id ? 1 : -1));
setDataFilter(res);
setSort(!sort);
console.log(res);
}
} else if (k === "age") {
if (sort) {
const res = USERS.sort((a, b) => (a.age > b.age ? 1 : -1));
setDataFilter(res);
setSort(!sort);
console.log(res);
} else {
const res = USERS.sort((a, b) => (a.age < b.agek ? 1 : -1));
setDataFilter(res);
setSort(!sort);
console.log(res);
}
} else if (k === "name") {
if (sort) {
const res = USERS.sort((a, b) => a.name.localeCompare(b.name));
setDataFilter(res);
setSort(!sort);
console.log(res);
} else {
const res = USERS.sort((a, b) => b.name.localeCompare(a.name));
setDataFilter(res);
setSort(!sort);
console.log(res);
}
} else {
console.log("hmm");
}
};
您可能希望在映射对象中对回调进行排序(按 属性 名称或 属性 类型)。
此外,不要忘记利用 useMemo()
/ useCallback()
钩子通过记忆排序输出来提高排序性能(这可能对大量项目有益):
const users = [
{ id: 1, name: "Andy", age: 32 },
{ id: 2, name: "Bob", age: 30 },
{ id: 3, name: "Tom Hulk", age: 40 },
{ id: 4, name: "Tom Hank", age: 50 },
{ id: 5, name: "Audra", age: 30 },
{ id: 6, name: "Anna", age: 68 },
{ id: 7, name: "Tom", age: 34 },
{ id: 8, name: "Tom Riddle", age: 28 },
{ id: 9, name: "Bolo", age: 23 },
],
sortDirection = {
'asc': 1,
'desc': -1
},
numericSorter = propName =>
sortOrder =>
({[propName]:a}, {[propName]:b}) =>
(a-b)*sortDirection[sortOrder],
stringicSorter = propName =>
sortOrder =>
({[propName]:a}, {[propName]:b}) =>
a.localeCompare(b)*sortDirection[sortOrder],
sortMap = {
id: numericSorter('id'),
name: stringicSorter('name'),
age: numericSorter('age')
},
sortUsers = (users, byProp, sortOrder) =>
users.sort(sortMap[byProp](sortOrder))
console.log(sortUsers(users, 'name', 'desc'))
console.log(sortUsers(users, 'age', 'asc'))
.as-console-wrapper{min-height: 100%;}
试试下面的代码。它检查排序键值的类型并相应地选择排序方法。我重新使用了您的逻辑,使您的操作变得简单。
const USERS = [
{ id: 1, name: "Andy", age: 32 },
{ id: 2, name: "Bob", age: 30 },
{ id: 3, name: "Tom Hulk", age: 40 },
{ id: 4, name: "Tom Hank", age: 50 },
{ id: 5, name: "Audra", age: 30 },
{ id: 6, name: "Anna", age: 68 },
{ id: 7, name: "Tom", age: 34 },
{ id: 8, name: "Tom Riddle", age: 28 },
{ id: 9, name: "Bolo", age: 23 },
];
const sortBy = (k, sort) => {
var res;
if( USERS[0] && (typeof USERS[0][k] == 'string')) {
res = sort ? USERS.sort((a, b) => a[k].localeCompare(b[k])) : USERS.sort((a, b) => b[k].localeCompare(a[k]));
} else {
const f = sort ? 1 : -1;
res = USERS.sort((a, b) => (a[k] > b[k] ? f : -f));
}
// setDataFilter(res);
// setSort(!sort);
console.log(res);
}
sortBy('name', 1);
sortBy('age', 1);
sortBy('name', 0);
sortBy('age', 0);