• react antd table表格点击一行选中数据的方法


    一、前言

    在这里插入图片描述

    antd的table,默认是点击左边的单选/复选按钮,才能选中一行数据;

    现在想实现点击右边的部分,也可以触发操作选中这行数据。

    可以使用onRow实现,样例如下。

    二、代码

    1.表格样式部分

    //表格table样式部分
    
    {isRadio ?
                     ({
                      onClick: () => {
                        this.selectRow(record);
                      },
                    })}
                    rowSelection={{
                      type: 'radio',
                      selectedRowKeys: selectedIdsInSearchTab,
                      onChange: this.onSelectChange,
                    }} // 表格是否可复选,加type是单选,去掉是多选
                    columns={this.getColumns()}
                    rowKey={record => record.id}
                    pagination={false}
                    loading={loading}
                    size="middle"
                    bordered
                    scroll={{ x: 1100 }}
                  /> 
              :
                  
    ({ onClick: () => { this.selectRow(record); }, })} rowSelection={{ selectedRowKeys: selectedIdsInSearchTab, onChange: this.onSelectChange, onSelect: this.onSelect, onSelectAll: this.onSelectAll, }} // 表格是否可复选,加type是单选,去掉是多选 columns={this.getColumns()} rowKey={record => record.id} pagination={false} loading={loading} size="middle" bordered scroll={{ x: 1100 }} /> }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    说明:
    (1)isRadio 是自己写的一个变量,用来区分是单选表格还是多选表格

    (2)onRowthis.selectRow(record)方法是核心,用来实现点击一行数据即可选中(其实是点击 单选/多选按钮右边的部分时,触发这个方法)

    (3)onChange: this.onSelectChange,这个方法是点击左边的单选/多选按钮时,会触发;

    但是由于框架自身bug,翻页多选数据的话,id数组没有问题、内容数组会只保留当前页、无法保留前几页选中的内容;
    所以多选时增加了onSelectonSelectAll方法,可以解决这个问题。

    (4)加上 type: 'radio',表格就会展示为单选按钮;去掉,表格默认展示为多选按钮

    (5)selectedRowKeys: selectedIdsInSearchTab,这个是保存选中行id的一个数组,必须加,数组有内容后,页面就会显示出哪行被选中的样式

    2.onRowthis.selectRow(record)方法

    
      selectRow = (record) => {
    
        const {
          dispatch,
          TrainPlanManage_SelectBscUserT: { selectedIdsInSearchTab,selectedRowsInSearchTab },
          isRadio
        } = this.props;
    
        //如果是单选
        if(isRadio){
          //获取存放的key
          const selectedRowKeys = [record.id];
          //获取存放的数据value
          const selectedRows = [record];
    
          dispatch({
            type: 'TrainPlanManage_SelectBscUserT/updateSelectedIdsInSearchTab',
            selectedIds : selectedRowKeys,
            selectedRows: selectedRows,
          });
        }
        //否则是多选
        else{
    
          //获取存放的key
          const selectedRowKeys = [...selectedIdsInSearchTab];
          //获取存放的数据value
          const selectedRows = [...selectedRowsInSearchTab];  
          
          if (selectedRowKeys.indexOf(record.id) >= 0) {
            //当点击选中的数据,取消选中
            selectedRowKeys.splice(selectedRowKeys.indexOf(record.id), 1);
            //取消选中也要删除数组中的value
            selectedRows.forEach((element,index) => {
              if(element.id === record.id){
                //根据id获取到数组里当前数据的下标,并删除。
                selectedRows.splice(index,1)
              }
            });
          } else {
            selectedRowKeys.push(record.id);
            //将选中的数据加入数组里
            selectedRows.push(record)
          }
          
          //this.setState({ selectedRowKeys,selectedRows });    
    
          dispatch({
            type: 'TrainPlanManage_SelectBscUserT/updateSelectedIdsInSearchTab',
            selectedIds : selectedRowKeys,
            selectedRows: selectedRows,
          });
        }
    
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    说明:

    (1)TrainPlanManage_SelectBscUserT: { selectedIdsInSearchTab,selectedRowsInSearchTab }的意思是,从TrainPlanManage_SelectBscUserT.js里拿出2个变量来,selectedIdsInSearchTab是保存被选中id的数组,selectedRowsInSearchTab 是保存被选中整行数据的数组

    (2)入参record,就是当前点击的行数据,单选时直接保存回那2个变量中即可;
    多选时,先判断现有数组中是否存在当前点击行的id,如果存在,那就是取消选择的意思,从数组移除内容;
    如果不存在,那就是新增,直接放入数组。

    (3)selectedRows.splice(index,1)的意思是,从数组中删除下标为index的数据。

    (4)dispatch方法,调用的是TrainPlanManage_SelectBscUserT.js里的方法,把处理好的数组保存进去用,如下:

    export default {
      namespace: 'TrainPlanManage_SelectBscUserT',
    
      state: {
          selectedIdsInSearchTab:[],
          selectedRowsInSearchTab:[],
    
    ......
    
    ---------------------------------------
      reducers: {
      
        updateSelectedIdsInSearchTab(state, action) {
          return {
            ...state,
            selectedIdsInSearchTab: action.selectedIds || state.selectedIds,
            selectedRowsInSearchTab: action.selectedRows || state.selectedRows,
          };
        },
        
    }    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    (5)如果变量在同一个js中,也可以使用//this.setState({ selectedRowKeys,selectedRows }); 来保存。

    3.onChange: this.onSelectChange方法

    这个方法是点击左边的 单选/复选 按钮 触发的;

    单选没有问题;

    多选有问题,上方提到了,不过自己把onSelectonSelectAll方法加上,就可以解决问题,后续会有。

    代码如下:

      // 复选框选中后的方法
      onSelectChange = (selectedIds, selectedRows) => {
    
        const {
          dispatch,
          TrainPlanManage_SelectBscUserT: { selectedIdsInSearchTab,selectedRowsInSearchTab },
          isRadio
        } = this.props;
    
        //如果是单选
        if(isRadio){
          //和原来保持一致
          dispatch({
            type: 'TrainPlanManage_SelectBscUserT/updateSelectedIdsInSearchTab',
            selectedIds,
            selectedRows,
          });
        }
        //否则是多选
        else{
    
          //这里管选中的行,都放到这个数组里
          if(selectedRowsInSearchTab !== null && selectedRowsInSearchTab !== '' && selectedRowsInSearchTab !== undefined) {
            for(let index in selectedRows){
              let flag = false;
              let id = selectedRows[index].id;
              for(let i in selectedRowsInSearchTab){
                if(selectedRowsInSearchTab[i].id === id){
                  flag = true;
                }
              }
              if(!flag){
                selectedRowsInSearchTab.push(selectedRows[index]);
              }
            }
          }
    
          //然后放回去
          dispatch({
            type: 'TrainPlanManage_SelectBscUserT/updateSelectedIdsInSearchTab',
            selectedIds,
            selectedRows: selectedRowsInSearchTab,
          });
    
        }
    
      };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    说明:
    (1) 这个方法入参是选中行的id数组和选中行的数据数组。

    (2)dispatch方法与上方相同,就是把数组直接保存进去。

    (3)多选时,主要负责把多选的行保存进去,有去重。(解决框架翻页多选后只有当前行数据、没有之前页选中行数据的问题)

    4.onSelect: this.onSelect方法

    这个是点击列表左边部分的方框会触发的方法(点击右边的行部分不会触发)

    代码如下:

      onSelect = (record,selected,selectedRows,nativeEvent) => {
    
        const {
          dispatch,
          TrainPlanManage_SelectBscUserT: { selectedIdsInSearchTab,selectedRowsInSearchTab },
          isRadio
        } = this.props;
    
        //如果取消选择,那就删掉数组元素
        if(selectedRowsInSearchTab !== null && selectedRowsInSearchTab !== '' && selectedRowsInSearchTab !== undefined){
          if(!selected){
            for(const index in selectedRowsInSearchTab){
              if(record.id === selectedRowsInSearchTab[index].id){
                selectedRowsInSearchTab.splice(index,1);
              }
            }
          }
        }
    
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    说明:
    这个负责取消选中行时,把行元素从数组中移除。(选中行时onChange负责装入元素了,这里不用管)

    5.onSelect: this.onSelectAll方法

    这个是点击列表左上方的全选方框会触发的方法

    代码如下:

      onSelectAll = (selected,selectedRows,changeRows) => {
    
        const {
          dispatch,
          TrainPlanManage_SelectBscUserT: { selectedIdsInSearchTab,selectedRowsInSearchTab },
          isRadio
        } = this.props;
        
        //如果取消选择,那就删掉数组元素
        if(selectedRowsInSearchTab !== null && selectedRowsInSearchTab !== '' && selectedRowsInSearchTab !== undefined){
          if(!selected){
            for(const i in changeRows){
              let record = changeRows[i];
              for(const index in selectedRowsInSearchTab){
                if(record.id === selectedRowsInSearchTab[index].id){
                  selectedRowsInSearchTab.splice(index,1);
                }
              }
            }
          }
        }
    
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    说明:
    这个负责取消选中行时,把行元素从数组中移除。(选中行时onChange负责装入元素了,这里不用管)

    三、总结

    1.这个方法可以实现点击表格行选中一行数据。

    2.这个方法解决了翻页后、选中行数组丢失之前页的选中行、只保留当前页选中行的问题。(点击左边的选择框和右边的行都可以正常使用)

    3.需要自己写onRow、onChange、onSelect、onSelectAll这4个方法

    4.onRow实现点击行可以选中/取消选中本行;onChange负责点击左边按钮把选中数据放入数组;onSelect/onSelectAll负责点左边按钮取消选中时把数据从数组中移除。

    5.打印日志发现,框架先执行onChange,后执行onSelect,不影响数据的放入/移除数组。(后续优化的话,应该可以把放入/移除操作写到一个方法里?比如都写onSelect里面)

    四、备注

    1.发现,rowKey={record => record.id}这个东西,是配置返回列表的哪个字段作为table中元素的id;如果列表返回有id的话,把id装入selectedRowKeys: selectedIdsInSearchTab中的selectedIdsInSearchTab数组,页面就会显示哪些行被选中;

    但是如果数据列表没有叫id的字段,那么把其它值装入绑定数组selectedIdsInSearchTab没有效果,页面不知道选中的是哪行;

    如果打印onChange里的selectedIds数组,会发现框架自己默认生成了一个数组当做了该行的id(比如0,1,2),后续用于实现选中行效果等。

    所以,如果数据列表没有叫id的字段,那就修改rowKey={record => record.myid}这个东西,找到一个唯一值作为id才行。

  • 相关阅读:
    宋明的结局揭示了什么
    BO(Business Object)是一种用于表示业务对象的设计模式
    Elasticsearch(一)-基本概念与环境搭建
    《nginx》三、nginx负载均衡
    工作和生活中,如何用项目管理思维解决复杂的事情?
    第四章分类问题
    图文并茂——队列的实现 ,C语言实现
    【主流技术】ElasticSearch 在 Spring 项目中的实践
    【云原生】Nacos-TaskManager 任务管理的使用
    VBA之正则表达式(37)-- 去除无意义的零
  • 原文地址:https://blog.csdn.net/BHSZZY/article/details/133749427