element-plus中el-table分页勾选记住勾选内容并限制数量

文章介绍了如何在升级到Vue3和Element-Plus的项目中处理列表分页时保持跨页选择的状态,包括使用row-key、reserve-selection以及自定义方法来管理选中项,同时实现数量限制和全选/取消全选功能。

需求背景,定制需求,列表分页+数量限制提交

前提条件:由于历史项目升级到vue3+element-plus ,故此写法还是偏于vue2的声明写法,没有用到组合式

有过研究的小伙伴们,肯定发现了,element 和element-plus中对于跨页选择保持勾选这个操作,源码进行更改,如果用element的话,用row-key + reserve-selection 即可达到切换分页时,记住之前分页的数据内容,但是element-plus可不行。

下面在线模拟一波

 然后同样的后端分页使用element,切换分页时也可以达到记忆之前勾选内容,但是element-plus按照这种方式并不能实现。

先来看一波element-plus实现的样例:

 这边我设置勾选上限25个,后端分页,切换分页记住之前选择,并达到上限之后,复选框禁用,搭配上全选功能也实现限制。

前提准备:

1.使用row-key定唯一字段、reserve-selection在type=selection勾选框栏(开启跨页记录) 使用selectable属性来控制是否可以勾选

2.尝试@select和@select-change 两个方法,发现select-change不记录跨页数据,故而采用@select,勾选单个勾选框触发的事件,可以知道当前点击行的row信息

3. @select-all 方法全选该页所有项,参数是目前选中的数据,开启跨页记录(含跨页数据)

实现思路:

1.单个选择时,判断选中的行数据是否存在选中数据数组中(currentSelection),不存在就加入存在就剔除

2.全部选择时:分两种情况 @select-all = handlerSelectAll(val)

a: val 为空 取消当前页勾选,并且其他页都没有数据   ===> 直接维护currentSelection 置空即可

b: val有数据 分两种情况

      b1: 当前页的全选

       比较当前页tableData和val差集(diff),如果tableData的数据都在val中,说明是全选,将差集添加到currentSelection即可

        b2: 其他页有数据勾选,当前页取消全选

        如果tableData的数据在val中不存在,则为取消全选,从currentSelection 剔除这些数据即可

    上述分析中再加入上限设置,全选时判断,增加差集过程中,currentSelection + diff 和 上限(maxLength) 作对比,超过限制就截断,不足就直接添加

分析完毕:下面是展示代码

<el-table
   v-show="!tableLoading && tableData.length"
   max-height="330"
   ref="multipleTable"
   :data="tableData"
   class="userCameraTable"
   row-class-name="rowClassName"
   header-row-class-name="headerRowClassName"
   border
   row-key="deviceId"
   @select="handlerSelect"
   @select-all="handlerSelectAll"
 >
   <el-table-column
     label
     width="50"
     type="selection"
     v-if="!isShowDetail"
     :selectable="handlerSelectable"
     :reserve-selection="true"
   />
  ....
handlerSelectable(row) {
  // 检查当前行是否已被选择
  const isChecked = this.currentSelection.includes(row.deviceId)
  // 如果当前行已被选择,则允许取消选择
  if (isChecked) {
     return true
  } else {
    // 如果当前行未被选择,并且已选择的行数超过max,则禁止选择新的行
     return this.currentSelection.length < this.maxLength
   }
 },
 handlerSelect(val, row) {
    this.currentSelection.indexOf(row.deviceId) === -1
      ? this.currentSelection.push(row.deviceId)
      : this.currentSelection.splice(this.currentSelection.indexOf(row.deviceId), 1)
 },
 handlerSelectAll(val) {
   if (val.length) {
     // 进来此处说明:
     // 1 当前页的全选 2 其他页有数据然后当前页的取消全选
     // 比较全选或者取消全选与当前页的数据,得到差集
     // 如果tableData中的数据在val中不存在,则说明是取消全选,需要从currentSelection中移除
     // 如果tableData中所有的数据都在val中存在,则说明是全选,需要将差集添加到currentSelection中
     const isAllSelect = this.tableData.every(item =>
     val.some(valItem => valItem.deviceId === item.deviceId)
    )
    if (isAllSelect) {
       // 全选中新增的差集
      const diff = val.filter(
      item => !this.currentSelection.some(deviceId => deviceId === item.deviceId)
     )
     if (this.currentSelection.length + diff.length > this.maxLength) {
         this.currentSelection = this.currentSelection.concat(
           diff.splice(0, this.maxLength - this.currentSelection.length)
              .map(item => item.deviceId))
         diff.forEach(item => this.$refs.multipleTable.toggleRowSelection(item, false))
     } else {
         this.currentSelection = this.currentSelection.concat(diff.map(item => item.deviceId))
     }
    } else {
        this.currentSelection = this.currentSelection.filter(
          deviceId => !this.tableData.some(item => item.deviceId === deviceId)
        )
      }
    } else {
      // 进来此处说明:
      // 其他页并无勾选数据,且当前页取消勾选
      this.currentSelection = []
    }
  },


// getTableData 
async getCameraList() {
...
const res = await this.$api.getCameraListByGroup(data)
  if (res.cameraList && res.cameraList.length) {
      this.totalNum = res.pageInfo.totalNum
      this.tableData = res.cameraList
// 需要这部分,每当切换分页获取新一页的tableData时,双循环遍历把当前tableData中有存在维护已选数据中的id手动设置勾选
      if (this.currentSelection.length) {
            this.$nextTick(() => {
              this.currentSelection.forEach(row => {
                this.tableData.forEach(item => {
                  if (item.deviceId === row) {
                    this.$refs.multipleTable?.toggleRowSelection(item, true)
                  }
                })
              })
            })
          } else {
            this.$refs.multipleTable?.clearSelection()
          }
          this.$nextTick(() => {
            this.$refs.multipleTable?.doLayout()
            this.$refs.multipleTable?.setScrollTop(0)
          })
        }
...
      } 
    }

至于打开弹框再回显数据,就让后端返参,返回所有的勾选数据,前端直接赋值ids给currentSelection即可。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值