可扩展 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);