Javascript 如何在reactjs中创建一个函数来按属性对对象数组进行排序?

Javascript 如何在reactjs中创建一个函数来按属性对对象数组进行排序?,javascript,reactjs,sorting,Javascript,Reactjs,Sorting,我需要创建一个用于排序对象数组的函数。数组如下所示: array=[ 0: {id: "7", name: "Aaaaa", level: "3/4", generation: "2", area: "JavaScript", …} 1: {id: "6", name: "Bbbbbb", level: "2/4", generation

我需要创建一个用于排序对象数组的函数。数组如下所示:

array=[ 0: {id: "7", name: "Aaaaa", level: "3/4", generation: "2", area: "JavaScript", …} 1: {id: "6", name: "Bbbbbb", level: "2/4", generation: "2", area: "JavaScript", …} 2: {id: "10", name: "DEV #1", level: "1/1", generation: "1", area: "Development", …} ]
<span className="margin-h-10 row align-center padding-r-5 pointer"
                        onClick={() => {
                            this.setState({ asc: !this.state.asc });
                            this.props.sortHandle('name', this.state.asc)
                        }}>
                        <span className="margin-r-5">Name</span>
                        <FontAwesomeIcon
                            icon={this.state.asc ? 'chevron-up' : 'chevron-down'}
                            style={{ color: "#7f7f7f", fontSize: "10px" }}
                        />
                    </span>
                    <span className="margin-h-10 row align-center padding-r-5 pointer"
                        onClick={() => {
                            this.setState({ asc: !this.state.asc });
                            this.props.sortHandle('date', this.state.asc)
                        }}>
                        <span className="margin-r-5">Date</span>
这就是
i
调用函数的方式

sortHandle={() => this.sortArray("someProperty", "desc/asc")}
我已经设法使它的工作,但只有在我点击分拣机的第二次

sortCourses(sorter, asc) {
        let courses = this.state.courses;
        let sortedCourses = []
        switch (sorter) {
            case 'level':
                sortedCourses.push(courses.sort((a, b) => { return (parseInt(a.level) - parseInt(b.level)) ? 1 : -1 }))     
                break;
            case 'generation':
                sortedCourses.push(courses.sort((a, b) => { return (parseInt(a.generation) - parseInt(b.generation)) ? 1 : -1 }))
                break;
            case 'name':
                sortedCourses.push(courses.sort((a, b) => { return (a.name.toLowerCase() - b.name.toLowerCase()) ? 1 : -1 }))
            case 'area':
                sortedCourses.push(courses.sort((a, b) => { return (a.area.toLowerCase() - b.area.toLowerCase()) ? 1 : -1 }))
                break;
            case 'date':
                sortedCourses.push(courses.sort((a, b) => { return (a.startDate - b.startDate) ? 1 : -1 }))
                break;
        }
        this.setState({ courses: sortedCourses[0] }, () => { console.log(this.state.courses) })

        if (asc) {
            return sortedCourses[0]
        }
        else if (!asc) {
            return sortedCourses[0].reverse()
        }
    }
我从props sortHandle获得sortProperty和asc/desc,它是子组件中的一个函数

sortHandle={(sorter,asc) => this.sortCourses(sorter,asc)}
在我的子组件中,排序器如下所示:

array=[ 0: {id: "7", name: "Aaaaa", level: "3/4", generation: "2", area: "JavaScript", …} 1: {id: "6", name: "Bbbbbb", level: "2/4", generation: "2", area: "JavaScript", …} 2: {id: "10", name: "DEV #1", level: "1/1", generation: "1", area: "Development", …} ]
<span className="margin-h-10 row align-center padding-r-5 pointer"
                        onClick={() => {
                            this.setState({ asc: !this.state.asc });
                            this.props.sortHandle('name', this.state.asc)
                        }}>
                        <span className="margin-r-5">Name</span>
                        <FontAwesomeIcon
                            icon={this.state.asc ? 'chevron-up' : 'chevron-down'}
                            style={{ color: "#7f7f7f", fontSize: "10px" }}
                        />
                    </span>
                    <span className="margin-h-10 row align-center padding-r-5 pointer"
                        onClick={() => {
                            this.setState({ asc: !this.state.asc });
                            this.props.sortHandle('date', this.state.asc)
                        }}>
                        <span className="margin-r-5">Date</span>
{
this.setState({asc:!this.state.asc});
this.props.sortHandle('name',this.state.asc)
}}>
名称
{
this.setState({asc:!this.state.asc});
this.props.sortHandle('date',this.state.asc)
}}>
日期

这似乎很好,但只有在我点击分拣机2次之后。我想这和国家有关。有什么解决方案吗?

也许你需要这样的解决方案

列表是您的数组

是要对其进行排序的键

如果要对
asc
进行排序,则
isAsc
true
;如果要使用
desc
进行排序,则
false

compareStr = key => (a, b) => {
    if (a[key] < b[key]) {
        return -1
    }
    if (a[key] > b[key]) {
        return 1
    }
    return 0
}

sortArray = (list, key, isAsc) => {
    if (!list || !list.length) return []
    const duplicate = [...list]
    if (typeof duplicate[0][key] === 'number' || Number(duplicate[0][key])) {
        duplicate.sort((a, b) =>
            isAsc
                ? Number(a[key]) - Number(b[key])
                : Number(b[key]) - Number(a[key])
        )
        return duplicate
    }
    duplicate.sort(compareStr(key))
    if (isAsc) return duplicate
    return duplicate.reverse()
}
compareStr=key=>(a,b)=>{
如果(a[键]b[键]){
返回1
}
返回0
}
sortArray=(列表、键、isAsc)=>{
如果(!list | |!list.length)返回[]
常量重复=[…列表]
如果(重复[0][key]的类型=='number'| | number(重复[0][key])){
重复。排序((a,b)=>
isAsc
?编号(a[键])-编号(b[键])
:编号(b[键])-编号(a[键])
)
返回副本
}
重复。排序(比较(键))
如果(isAsc)返回副本
返回replicate.reverse()
}
如果数组中的数字是数字,而不是字符串,那么这将很好地工作。
因此,您可以选择或更改数字类型,或者您可以添加自己的数字大小写检查,而不是此
if(typeof duplicate[0][key]='number'){

这里有一个简单的小技巧。你不需要在事件处理程序中进行排序-你只需要在渲染中进行排序,只需要维护有关排序属性和顺序的信息。此外,你只需要将排序器的返回值乘以
-1
如果要将顺序更改为降序

首先,我将提取分拣机本身:

const sorters = {
  level: (a, b) => parseInt(a.level) - parseInt(b.level),
  generation: (a, b) => parseInt(a.generation - b.generation),
  name: (a, b) => a.name.localeCompare(b.name),
  area: (a, b) => a.area.localeCompare(b.area),
};
很简单。然后,我会把这些和排序顺序一起放入您的状态:

const SortOrder = {
  ASC: 1,
  DESC: -1,
};

// ...

state = {
  sortOrder: SortOrder.ASC,
  sortProperty: "level",
  array: [],
  // ...
};
sortArray = (property, order) => {
  this.setState({
    sortProperty: property,
    sortOrder: order === "asc" ? SortOrder.ASC : SortOrder.DESC,
  });
};
然后,在
render()
中,您只需获取阵列并根据分类器对其进行排序:

render() {
  const { array, sortProperty, sortOrder } = this.state;
  const arraySorter = sorters[sortProperty];
  const displayArray = [...array].sort(
    (a, b) => arraySorter(a, b) * sortOrder
  );

  return (
    <>
      {displayArray.map((item) => (
        <p key={item}>{item}</p>
      ))}
    </>
  );
}
这里的API与您的API相同,即this.sortArray('level','desc')
,但老实说,您可以直接将
订单
传递到
排序器
,并像调用
()=>this.sortArray('level',sortOrder.desc')一样调用它
。或者完全从函数中删除订单,因为您现在可以将其与属性分开更改

总而言之:

const SortOrder = {
  ASC: 1,
  DESC: -1,
};

const sorters = {
  level: (a, b) => parseInt(a.level) - parseInt(b.level),
  generation: (a, b) => parseInt(a.generation - b.generation),
  name: (a, b) => a.name.localeCompare(b.name),
  area: (a, b) => a.area.localeCompare(b.area),
};

class MyComponent extends React.Component {
  state = {
    sortOrder: SortOrder.ASC,
    sortProperty: "level",
    array: [],
    // ...
  };

  sortArray = (property, order) => {
    this.setState({
      sortProperty: property,
      sortOrder: order === "asc" ? SortOrder.ASC : SortOrder.DESC,
    });
  };

  render() {
    const { array, sortProperty, sortOrder } = this.state;
    const arraySorter = sorters[sortProperty];
    const displayArray = [...array].sort(
      (a, b) => arraySorter(a, b) * sortOrder
    );

    return (
      <>
        {displayArray.map((item) => (
          <p key={item}>{item}</p>
        ))}
      </>
    );
  }
}
const SortOrder={
ASC:1,
描述:-1,
};
常量分拣机={
级别:(a,b)=>parseInt(a.level)-parseInt(b.level),
生成:(a,b)=>parseInt(a.generation-b.generation),
name:(a,b)=>a.name.localeCompare(b.name),
面积:(a,b)=>a.area.localeCompare(b.area),
};
类MyComponent扩展了React.Component{
状态={
sortOrder:sortOrder.ASC,
sortProperty:“级别”,
阵列:[],
// ...
};
Sortaray=(属性、顺序)=>{
这是我的国家({
sortProperty:属性,
sortOrder:order==“asc”?sortOrder.asc:sortOrder.DESC,
});
};
render(){
const{array,sortProperty,sortOrder}=this.state;
const arraySorter=分拣机[分拣属性];
常量displayArray=[…数组].sort(
(a,b)=>阵列排序器(a,b)*排序器
);
返回(
{displayArray.map((项)=>(

{item}

))} ); } }
如果你不反对使用软件包,那么它适合排序需要使用简单排序:然后将状态设置为排序数组:
this.setState([…array].sort(…)
简单排序对数字不起作用无耻的自我插入:我为排序函数编写了一个助手,可能很方便:这个函数的功能()=>这个.sortArray('level','desc')是我需要从子组件的状态中获取函数参数。这意味着当我单击子组件中的某个分类器时,它触发一个通过其状态(属性,顺序)的onClick事件在父组件中使用sortArray。如果我没有很好地解释它,那么很抱歉。我仍在学习react,而且我的英语不太好。这帮了大忙。我修改了代码,只返回sortArray.reverse(),如果order==='desc',它可以工作