Javascript 什么';使用React实现可排序表的正确方法是什么?
我目前的执行情况:Javascript 什么';使用React实现可排序表的正确方法是什么?,javascript,reactjs,Javascript,Reactjs,我目前的执行情况: export const SORT_ORDER = { ASC: "ascending", DESC: "descending", OTHER: "other" }; export default class Table extends React.Component { constructor(props) { super(props); this.sortIcon = new Map();
export const SORT_ORDER = {
ASC: "ascending",
DESC: "descending",
OTHER: "other"
};
export default class Table extends React.Component {
constructor(props) {
super(props);
this.sortIcon = new Map();
this.sortIcon.set(SORT_ORDER.ASC, sortAsc);
this.sortIcon.set(SORT_ORDER.DESC, sortDesc);
this.sortIcon.set(SORT_ORDER.OTHER, sortOther);
this.state = {
sortField: this.props.defaultSortColumn,
sortOrder: this.props.defaultSortOrder
};
}
componentDidMount() {
this.sort(this.props.defaultSortColumn, this.props.defaultSortOrder)();
}
retrieveOrder = (columnId) => {
return columnId === this.state.sortField ? this.state.sortOrder : SORT_ORDER.OTHER;
};
nextOrder = (current) => {
if (current === SORT_ORDER.DESC) {
return SORT_ORDER.ASC;
} else if (current === SORT_ORDER.ASC) {
return SORT_ORDER.DESC;
} else {
return this.props.defaultSortOrder;
}
};
sort = (columnId, order) => () => {
let descriptor = this.props.structure[columnId];
let values = this.props.value.slice();
let orderFactor = order === SORT_ORDER.ASC ? 1 : -1;
values.sort((a, b) => {
let first = descriptor.render(a);
let second = descriptor.render(b);
return first > second ? orderFactor : first < second ? -orderFactor : 0;
});
this.setState({
sortField: columnId,
sortOrder: order
});
this.props.onSort(values);
};
renderHeader = (id, descriptor) => {
let order = this.retrieveOrder(id);
let iconSrc = this.sortIcon.get(order);
let nextOrder = this.nextOrder(this.retrieveOrder(id));
return (
<th key={id} className={descriptor.headStyle}>
<a href="#" aria-sort={order} onClick={this.sort(id, nextOrder)}>
<img src={iconSrc}/>
{descriptor.label}
</a>
</th>
);
};
render() {
return (
<table>
Table structure
</table>
);
}
}
导出常量排序\u顺序={
ASC:“上升”,
描述:“下降”,
其他:“其他”
};
导出默认类表扩展React.Component{
建造师(道具){
超级(道具);
this.sortIcon=新地图();
this.sortIcon.set(SORT\u ORDER.ASC,sortAsc);
this.sortIcon.set(SORT_ORDER.DESC,sortDesc);
this.sortIcon.set(排序顺序、其他、排序);
此.state={
sortField:this.props.defaultSortColumn,
sortOrder:this.props.defaultSortOrder
};
}
componentDidMount(){
this.sort(this.props.defaultSortColumn,this.props.defaultSortOrder)();
}
检索顺序=(列ID)=>{
return columnId===this.state.sortField?this.state.sortOrder:SORT\u ORDER.OTHER;
};
nextOrder=(当前)=>{
如果(当前===排序顺序.DESC){
返回SORT_ORDER.ASC;
}else if(当前===SORT\u ORDER.ASC){
返回SORT_ORDER.DESC;
}否则{
返回此.props.defaultSortOrder;
}
};
排序=(列ID,顺序)=>()=>{
让descriptor=this.props.structure[columnId];
让values=this.props.value.slice();
让orderFactor=order==SORT\u order.ASC?1:-1;
值。排序((a,b)=>{
设first=descriptor.render(a);
设second=descriptor.render(b);
返回第一个>第二个?orderFactor:first{
let order=this.retrieveOrder(id);
让iconrc=this.sortIcon.get(order);
设nextOrder=this.nextOrder(this.retrieveOrder(id));
返回(
);
};
render(){
返回(
表结构
);
}
}
父组件以下一种方式声明它:
<Table structure={this.tableHeader} value={this.state.tableValue} onSort={this.handleChange('tableValue')}
defaultSortColumn="created" defaultSortOrder={SORT_ORDER.DESC} />
表值在props中定义为value
onSort
是一个更改父组件状态的函数=>它更改表值。此外,我还有defaultSortColumn
和defaultSortOrder
来在表格填充后对其进行排序
问题是我的表可以在页面上声明多次
所以
1) 我无法将表值存储在其状态。我应该吗
2) 如何在不使用componentDidMount
的情况下实现默认排序?使用当前实现时,当调用componentDidMount
时,默认排序只发生一次,但我在页面上有多个
组件。
我尝试使用组件willreceiveprops
函数,但在排序
函数中更改
状态时也会调用该函数。所以我不能使用它。我的最终解决方案是:
export const SORT_ORDER = {
ASC: "ascending",
DESC: "descending",
OTHER: "other"
};
class TableRow extends React.Component {
render() {
return (
<tr>
{this.props.children}
</tr>
);
}
}
class TableHeader extends React.Component {
constructor(props) {
super(props);
this.sortIcon = new Map([
[SORT_ORDER.ASC, {icon: sortAsc, title: "Ascending"}],
[SORT_ORDER.DESC, {icon: sortDesc, title: "Descending"}],
[SORT_ORDER.OTHER, {icon: sortOther, title: "Unsorted"}]
]);
}
render() {
const {children, onClick, sortOrder} = this.props;
return (
<th>
{onClick ? (
<a href="#" aria-sort={sortOrder} onClick={onClick}>
<img src={this.sortIcon.get(sortOrder).icon} title={this.sortIcon.get(sortOrder).title} />
{children}
</a>
) : children}
</th>
);
}
}
export default class Table extends React.Component {
constructor(props) {
super(props);
this.state = {
sortField: props.defaultSortColumn,
sortOrder: props.defaultSortOrder
};
}
retrieveOrder = (columnId) => {
return columnId === this.state.sortField ? this.state.sortOrder : SORT_ORDER.OTHER;
};
nextOrder = (current) => {
if (current === SORT_ORDER.DESC) {
return SORT_ORDER.ASC;
} else if (current === SORT_ORDER.ASC) {
return SORT_ORDER.DESC;
} else {
return this.props.defaultSortOrder;
}
};
sortedRows = () => {
let descriptor = this.props.structure.find(d => d.attribute === this.state.sortField);
let values = this.props.value.slice();
let orderFactor = this.state.sortOrder === SORT_ORDER.ASC ? 1 : -1;
return values.sort((a, b) => {
let first;
let second;
// null and undefined values should be changed to empty string
if (typeof a[descriptor.attribute] === "number" || typeof b[descriptor.attribute] === "number") {
first = a[descriptor.attribute] || "";
second = b[descriptor.attribute] || "";
} else {
first = descriptor.render(a) || "";
second = descriptor.render(b) || "";
}
return first > second ? orderFactor : first < second ? -orderFactor : 0;
});
};
renderHeaders = () => {
return this.props.structure.map((descriptor, id) => {
let header;
if (this.props.sortable) {
const order = this.retrieveOrder(descriptor.attribute);
const nextOrder = this.nextOrder(order);
header = (
<TableHeader key={id} onClick={() => {this.setState({sortField: descriptor.attribute, sortOrder: nextOrder})}}
sortOrder={order}>
{descriptor.label}
</TableHeader>
)
} else {
header = (
<TableHeader key={id}>
{descriptor.label}
</TableHeader>
)
}
return header;
});
};
renderRows = () => {
const Row = this.props.customRow || TableRow;
const values = this.props.sortable ? this.sortedRows() : this.props.value;
return values.map((value, idx) => (
<Row key={idx} value={value}>
{this.props.structure.map((descriptor, id) => (
<td key={id}>
descriptor.render(value, idx)
</td>
))}
</Row>
));
};
render() {
return (
<table className={this.props.className}>
<thead>
<tr>
{this.renderHeaders()}
</tr>
</thead>
<tbody>
{this.renderRows()}
</tbody>
</table>
);
}
}
导出常量排序\u顺序={
ASC:“上升”,
描述:“下降”,
其他:“其他”
};
类TableRow扩展了React.Component{
render(){
返回(
{this.props.children}
);
}
}
类TableHeader扩展了React.Component{
建造师(道具){
超级(道具);
this.sortIcon=新地图([
[SORT_ORDER.ASC,{icon:sortAsc,title:“升序”},
[SORT_ORDER.DESC,{icon:sortDesc,title:“Descending”},
[SORT_ORDER.OTHER,{icon:sortOther,title:“Unsorted”}]
]);
}
render(){
const{children,onClick,sortOrder}=this.props;
返回(
{onClick(
):children}
);
}
}
导出默认类表扩展React.Component{
建造师(道具){
超级(道具);
此.state={
sortField:props.defaultSortColumn,
sortOrder:props.defaultSortOrder
};
}
检索顺序=(列ID)=>{
return columnId===this.state.sortField?this.state.sortOrder:SORT\u ORDER.OTHER;
};
nextOrder=(当前)=>{
如果(当前===排序顺序.DESC){
返回SORT_ORDER.ASC;
}else if(当前===SORT\u ORDER.ASC){
返回SORT_ORDER.DESC;
}否则{
返回此.props.defaultSortOrder;
}
};
sortedRows=()=>{
让descriptor=this.props.structure.find(d=>d.attribute==this.state.sortField);
让values=this.props.value.slice();
让orderFactor=this.state.sortOrder==SORT\u ORDER.ASC?1:-1;
返回值。排序((a,b)=>{
让我们先来;
让我们再来一次;
//null和未定义的值应更改为空字符串
if(a[描述符.属性]的类型==“编号”| | b[描述符.属性]的类型==“编号”){
first=a[descriptor.attribute]| |“”;
second=b[descriptor.attribute]| |“”;
}否则{
first=描述符。呈现(a)| |“”;
second=descriptor.render(b)| |“”;
}
返回第一个>第二个?orderFactor:first{
返回此.props.structure.map((描述符,id)=>{
让标题;
if(this.props.sortable){
const order=this.retrieveOrder(descriptor.attribute);
const nextOrder=this.nextOrder(订单);
标题=(
{this.setState({sortField:descriptor.attribute,sortOrder:nextOrder}}}
排序器={order}>
{descriptor.label}
)
}否则{
this.tableStructure = [
{
attribute: "number", label: "Row Number"
render: (row) => {return row.number}
},
{
attribute: "created", label: "Creation time"
render: (row) => {return this.dateToString(row.created)}
},
{
attribute: "type", label: "Row Type"
render: (row) => {return row.type}
},
{
attribute: "state", label: "State",
render: (row) => {return row.state}
},
{
attribute: "action", label: "Action"
render: (row) => {
return (
<button onClick={this.doSomething}>
</button>
);
}
}
];
<Table structure={this.tableStructure} value={this.state.someValue} sortable
defaultSortColumn="created" defaultSortOrder={SORT_ORDER.DESC} />