关于AntD Table组件selectedRows翻页后不保留上一页已选中items的解决方案

关于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/

好的那么本期的营销号小讲堂就到这里了,我们下次再见哦~

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 41
    评论
评论 41
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值