关于AntD Table组件selectedRows翻页后不保留上一页已选中items的解决方案
问题描述
在用antd Table组件写一个产品选择框功能的时候,遇到了antd Table组件的selectedRows在翻页后再勾选新的item,不会保留上一页已勾选的item,而是基于当前页面的dataSource重新记录当前的勾选项(注:selctedRowKeys没有这个问题,可以正常的跨页记录总体的勾选项的key)。
解决方案(伪,主要B叨B,可以跳过)
先说点废话,这个问题其实也不是第一次遇到了,项目在一期的时候,并不需要实现pageSizeChanger的功能,就固定每页展示10个,然后当时我的做法是每当点击换页时(onPageChange),就在state里另外在用一个状态,我叫做(selectedRowsBefore)记录这个页码下的选中项,这是一个对象数组,每一页的记录作为一个对象,然后这个对象又包含一个pageNumber属性,以及一个对应页的items数组,最后确认选中这些项(产品勾选动作完成)的时候,把每一页的记录遍历拉平成一个数组就是总的选中项数组了。
但是现在需要做pageSizeChanger,每页的条数不固定了,于是这个方法就不行了,因为本来每页10条,现在我想改成每页50条,就得把前5页的记录重新映射成第1页的,或者本来每页50条,现在改成每页10条,就得把原来的第1页的记录按顺序拆分成5页的记录,这样做太笨拙了。
解决方案(真)
于是我就又去仔细看antd Table组件的官方文档,于是被我发现了两个个可以用的上的API,叫做onSelect和onSelectAll
首先我们可以看到onSelect需要传入一个函数作为回调,然后这个方法的参数里有record, selected, selectedRows这几项(nativeEvent原生事件我不关心),经过测试后确定
1、record就是当前操作(选中或取消选中)的item
2、selected是个布尔值,true代表本次是选中操作,false就是取消选中
3、selectedRows是一个数组,就是当前已选择的items(没有跨页的记录)
至于onSelectAll,是在点击全选和取消全选时触发的回调函数,截图中也可以看到,它有selected, selectedRows, changeRows这三个参数
1、selected,同上,true全选,false取消全选
2、selectedRows,也同上,当前已选择的items(没有跨页的记录)
3、changeRows,这个可就优秀了,它就是你的全选/取消全选操作引起变化的items数组,打个比方,如果一页10个,你一个都没选呢,点全选,就会新选择10个,那么changeRows就是这10条数据,如果你已经选了6条,你又点了全选,那么就相当于你又一次性选了4条,那么changeRows就是这4条
然后基于这些参数,我们来定义一个可以跨页记录的selectedRows,我取名叫selectedRowsPlus
constructor(props:any){
super(props);
this.state={
productListSelectedRowKeys: [],
productListSelectedRows:[],
productListSelectedRowsPlus:[],
};
}
然后是Table组件的rowSelection配置,
render(){
const { productListSelectedRowKeys,productListSelectedRows } = this.state;
const rowSelection = {
selectedRowKeys:productListSelectedRowKeys,
selectedRows:productListSelectedRows,
onSelect:this.onSelect,
onSelectAll:this.onSelectAll,
onChange: this.onProductListSelectedRowKeysChange,
columnWidth:'38px',
};
return(
<div>
<Table
className='productListTable'
dataSource={this.props.productListState.payLoad.records}
columns = {this.productListColumns}
scroll={{y:400}}
bordered
rowKey={(record:any) => record.id}
rowSelection={rowSelection}
pagination={false}
loading={this.props.productListState.loadingState}
size='small'
/>
</div>
)
}
然后是具体的回调方法的实现
//我看评论有人问补充一下,
//代码中个别地方用了lodash的深拷贝函数_.cloneDeep();
import * as _ from 'lodash';
onSelect = (record:any,selected:any,selectedRows:any,nativeEvent:any) => {
console.log("record:",record);
console.log("selected:",selected);
console.log("selectedRows:",selectedRows);
console.log("nativeEvent:",nativeEvent);
if(selected){
let productListSelectedRowsPlus = this.state.productListSelectedRowsPlus;
productListSelectedRowsPlus.push(record);
this.setState({productListSelectedRowsPlus});
}
if(!selected){
let productListSelectedRowsPlus = this.state.productListSelectedRowsPlus;
let delIndex = null;
for(let i=0;i<productListSelectedRowsPlus.length;i++){
if(productListSelectedRowsPlus[i].id==record.id){
delIndex = i;
break;
}
}
console.log(delIndex);
productListSelectedRowsPlus.splice(delIndex,1);
this.setState({productListSelectedRowsPlus});
}
}
onSelectAll = (selected:any,selectedRows:any,changeRows:any) =>{
console.log("selected:",selected);
console.log("selectedRows:",selectedRows);
console.log("changeRows:",changeRows);
if(selected){
let productListSelectedRowsPlus = this.state.productListSelectedRowsPlus;
this.setState({productListSelectedRowsPlus:productListSelectedRowsPlus.concat(changeRows)});
}
if(!selected){
let productListSelectedRowsPlus = _.cloneDeep(this.state.productListSelectedRowsPlus);
let delIndex = [];
for(let i=0;i<productListSelectedRowsPlus.length;i++){
for(let j=0;j<changeRows.length;j++){
if(changeRows[j].id==productListSelectedRowsPlus[i].id){
delIndex.push(i);
break;
}
}
}
console.log(delIndex);
for(let k=0;k<delIndex.length;k++){
delete productListSelectedRowsPlus[delIndex[k]];
}
let pureProductListSelectedRowsPlus = productListSelectedRowsPlus.filter((item:any)=>{
return item != undefined;
})
this.setState({productListSelectedRowsPlus:pureProductListSelectedRowsPlus});
}
}
onProductListSelectedRowKeysChange = (productListSelectedRowKeys:any,productListSelectedRows:any) => {
let a = _.cloneDeep(this.state.productListSelectedRows);
this.setState({
productListSelectedRowKeys,
productListSelectedRows
});
};
这样就可以保证我的selectedRowsPlus和selectedRowKeys的记录条数始终保持一致,就可以解决跨页选择的问题了。
第一次写博客,还挺好玩的。
对了,这是antd Table组件文档的链接
[1]: https://ant.design/components/table-cn/
好的那么本期的营销号小讲堂就到这里了,我们下次再见哦~