Bootstrap

实现table全选组件

背景
antd Table组件在升级到3.19.1版本后,通过选中checkbox来选中整行时,checkbox不能被选中,并报错“can’t read property shiftKey of undefined”
在这里插入图片描述
那就自己写一个吧。
还是要用antD的checkbox组件,毕竟样式还挺好看的。
DOM样式

import {Checkbox, Icon} from 'antd'; // 借用antD checkbox样式
<ul className={styles.multiBodyWrap}>
   {
         dataList && dataList.length > 0 && dataList.map((item) => {
             const {id, attend_date, subject, attend_status_list, student_name, attend_time} = item;
             return (
                 <li key={id} className={styles.multiBodyItem} onClick={this.rowChose.bind(this,id,attend_status_list)}> // 事件冒泡,选中整行
                     <Checkbox checked={selectedIdArr.indexOf(id) !== -1}></Checkbox>
                     <span className={`${isZouban ? styles.multiSubjectBDate : styles.multiBDate}`}>{attend_date}</span>
                     <span className={`${isZouban ? styles.multiSubjectBStatus : styles.multiBStatus}`}>{statesToNameObj[attend_status_list]}</span>
                     <span className={styles.multiBName}>{student_name}</span>
                     <span className={styles.multiBTime}>{attend_time}</span>
                 </li>
             );
         })
     }
 </ul>
 {/* 底部操作fixed框 */}
<div className={`${styles.footWrap} ${isMultiEdit && dataList && dataList.length!==0  ? '' : styles.hide}`}>
   <Checkbox onChange={this.selectAllMock.bind(this)} checked={selectedIdArr.length===allIdArr.length}>
   			<span className={styles.txt}>全选</span>
   </Checkbox>
   <span className={styles.edit}>
       {
           selectedIdArr && selectedIdArr.length > 0 ? editTxtActive : (<span className={styles.txtNormal}>修改状态</span>)
       }
   </span>
</div>

js部分
逐条选中

  • 样式上:

     利用selectedIdArr.indexOf(id) !== -1判断当前item的id是否在已选id数组selectedIdArr中,true时表示在该条目被选中,Checkbox为选中态。
    

antD Checkbox官方文档<Checkbox checked={selectedIdArr.indexOf(id) !== -1}>控制选中/取消样式

  • 功能上:

    主要介绍全选方法rowChose

// selectedIdArr:[], 选中的id都存放在此数组中
// allIdArr:[], 当前页面展示的所有数据的id组成的数组

此处为axios请求得到数据后,收集所有id


// 将数据中所有的id存在allIdArr数组中,全选用
let dataAllIds = [];
dataList && dataList.length > 0 && dataList.map((item) => {
    dataAllIds.push(item.id);
});
this.setState({
    allIdArr: dataAllIds,
});

利用事件冒泡,选中整行的点击事件


rowChose = (rowId,attend_status_list) => {
        let arr = JSON.parse(JSON.stringify(this.state.selectedIdArr)); // 深拷贝一个数组,防止对原数组进行不可预知干扰
        let location = arr.indexOf(rowId);
        if(location !== -1) { // 已经存在,说明现在是取消全选操作
            arr.splice(location,1);
            this.setState({
            	hasSelectAll:false, // 此处一定要记得将全选标识置为false
            });
        } else {
            arr.push(rowId)
        }
        this.setState({
            selectedIdArr: arr,
            selectedAttendType: attend_status_list,
        }, () => {
            let {allIdArr, selectedIdArr} = this.state;
            if(allIdArr.length === selectedIdArr.length) { // 请求得到dataList时,将
                this.setState({
                    hasSelectAll: true
                })
            }
        })
    }

注:
rowChose如果是取消当前选中行,要记得将将全选标识置为false。我在此处出过bug。bug复现路径是:
全选按钮-点击某行进行取消-全选按钮-结果全被取消了,而不是预期的全部选中。

一键全选功能

  • 样式上:

     判断selectedIdArr和allIdArr数组长度是否相等。
    
  • 功能上:

     全选:将allIdArr的值都赋给selectedIdArr;
     取消全选:清空selectedIdArr数组。
    
// 底部fixed区的全选按钮功能
selectAllMock = () => {
    let {allIdArr} = this.state;
    this.setState({
        hasSelectAll: !this.state.hasSelectAll
    }, () => {
        let {hasSelectAll} = this.state;
        if(hasSelectAll){
            this.setState({
                selectedIdArr:allIdArr,
            });
        } else {
            this.setState({
                selectedIdArr:[],
            })
        }
    })
}

言简意赅
selectedIdArr:存在已选择item的id
allIdArr:所有数据的id组成的id全集
通过操作selectedIdArr数组中的元素增减来实现选中/取消

更新更新
在后期的自测中发现了一个很偶现的checkbox点击闪一下的问题。花了挺长时间解决,记录一下。
原因分析:
antD的checkbox本身具有点击事件,而我在它的父级li中又写了点击事件rowChose,所以:checkbox的点击事件冒泡到li的rowChose,和li本身的rowChose事件在短时间内快速触发,checkbox就呈现出了先选中又被取消的过程,表现出来就是闪了一下。

写到这里也才发现自己之前引用的antD checkbox写法是有问题的,应该将复选框后面要显示的部分全部放在(此处展示要显示的其他布局),然后利用Checkbox的onChange事件进行判断即可。

因为是我项目测试末期才发现的这个问题,再重写样式成本比较高,就只能“将错就错”,利用原生进行修补。遂做出如下修改:
1.给rowChose方法传参
在这里插入图片描述
2.利用节流原理
在这里插入图片描述

;