el-table选中所有数据(包括非当前页的数据)的实现

el-table选中所有数据(包括非当前页的数据)的实现

抛出问题

在日常使用table表格的时候,我们一般会分页来加载数据,不过有些时候又需要选中所有的数据来进行操作,例如:

  • 选中满足筛选条件后的商品来参加活动
  • 选中所有的记录来一次性删除
  • 编辑参加活动的商品时,把原本已参加活动的商品勾选上

在刚接触到这个需求的时候,我的第一反应是做不了,数据都没获取到怎么选中他嘛。后来有小伙伴建议让后端新定义一个字段,如isAll,点击了选中所有按钮后给后端传一个true告知其选中所有的数据。

不过这样也有几个问题:

  1. 点击按钮后,我们的table表格上的选择框并没有任何变化,用户无法准确的知道是否已经完成该操作
  2. 若用户选中全部后又取消某条数据,而后又选中,又取消·····而el-table的select事件无法判断出用户到底是选中还是取消,我又该如何告知服务器,用户随后有哪些操作呢?

尝试解决

  • 对于问题1,经过一番思考后发现,我们可以在获取当前页数据的时候判断isAll字段,根据其值来遍历获取到的数据,用el-table中的toggleRowSelection函数来选中当前页的每一项,如
    this.datalist = res.data; // datalist是表格绑定的数据,res.data是服务器响应的数据
    if (this.isAll) {
    this.datalist.forEach(item => {
    this.$refs.tableRef.toggleRowSelection(item, true)
    })
    }

  • 对于问题二则是没想到好办法,于是乎陷入了僵局。

    思考了几天后(恕我愚昧,想了几天才想出来),终于想到,干脆在点击选中全部的按钮后,让后端把所有筛选结果都发给我,将其存在selectedData数组中,同时用toggleRowSelection函数来选中当前的数据。之后每次触发select事件我就遍历selectedData,用indexOf判断select的这一行row是否在selectedData中,在则是取消选中,咱们从selectedData中删除该row;否则就是选中,push到selectedData中,在需要时再将selectedData传给后端
    handleSelect(rows, row) {
    if (this.selectedData.length !== 0) {
    let isInner = false; // 用来判断是否是选中
    let index = 0; // 用来记录某项数据在selectedData数组的索引,以便删除
    this.selectedData.forEach(item => {
    if (item.id === row.id) {
    // 有和select项的id相同,说明已在selectedData中,是要取消该项的选择
    isInner = true;
    // 记录下来要取消的数据在selectedData中的索引
    index = this.selectedData.indexOf(item);
    }
    });
    // 在selectedData中,则删除该项
    if (isInner) {
    // 用splice方法将要取消的数据从selectedData中删除,并return结束该次select
    return this.selectedData.splice(index, 1);
    }
    // 不在则push到selectedData中
    this.selectedData.push(row);
    } else {
    // 如果selectedData为空,则直接push进去
    this.selectedData.push(row);
    }
    }

  • OK,搞定!跑起来!咦···怎么这里还有个选中当前页的选择框······

再遇问题

在点击选中当前页的选择框时,并不会触发select事件,而是触发的select-all事件或者selection-change事件。这两个事件默认接收一个rows(变化的数据数组)参数,在取消选中时rows被重置为空。这就又遇到了几个问题

  1. rows会被重置为空数组,我们可以用rows是否为空来判断是选中还是取消选中,但是我怎么知道是哪些数据的选中状态变化了呢?
  2. 若翻页后切换当前页的选中状态,由于我们用reserve-selection和row-key来保存了其他页面的选中状态,所以取消选中时rows并没有被重置为空,那我们该怎么判断当前页的全选状态呢?
  3. 若当前页有部分数据是选中状态(编辑时带入进来的),我切换当前页的全选按钮,又该如何处理呢?

解决问题

在无数次尝试后,我找到了解决办法

  • 新增一个全局属性isSelectedAll,在触发select-all事件时取反,在翻页时重置为初始值false,我们再通过isSelectedAll来判断是否是全选

  • 当前页的变化的数据始终都是当前的所有数据,所以我们可以直接用table绑定的datalist来遍历判断,哪些数据是已在selectedData中的

    handleSelectAll (rows) {
    this.isSelectedAll = !this.isSelectedAll;
    if (this.isSelectedAll) {
    // 为true说明是选中了全选,把本页的数据加进去
    this.datalist.forEach(item => {
    let isInner = false;
    this.selectedData.forEach(sItem => {
    if (sItem.id === item.id) {
    isInner = true;
    }
    });
    if (!isInner) {
    this.selectedData.push(item);
    }
    });
    } else {
    // 为false说明是取消了全选,将本页的数据从selectedData中删除
    this.datalist.forEach(item => {
    this.selectedData.forEach(sItem => {
    if (item.id === sItem.id) {
    // 找到了对应的sItem,获得其索引,删除
    return this.selectedData.splice(this.selectedData.indexOf(sItem), 1);
    // index = this.selectedData.indexOf(sItem);
    }
    });
    });
    }
    },

总结

要做到全选所有数据,主要有以下几点

  • 从服务器拿到所有数据(这比较考验后端的算法了,如果拿得太慢,可能这里直接就超时报错了,当然,也可以只拿id过来,减小数据量),存在一个selectedData数组中
  • 用reserve-selection和row-key属性在翻页时保存数据的选择状态
  • 在select和select-all事件中分别判断选中的数据是否在selectedData,从而决定增删
  • 在select-all事件中可以用一个全局变量来判断是选中还是取消,请一定记得在在翻页时重置
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值