el-table一键选择全部行,切换分页后无法勾选

el-table一键全选,分页的完美支持

问题背景

现在有个需求,一个表格有若干条数据(假设数量大于20,每页10条,保证有2个以上分页即可)。

现在需要在表格上方加个全部选择的按钮,点击全部选择按钮时,可以把表格的复选框全部勾选,切换分页后依然是勾选状态,那么怎么实现呢?示意图如下:

尝试解决

我们平时做表格的勾选时,一般都用selection-change方法。

假设我们有个接口getAllTableIds返回数据的全部id,那么我们尝试以下方法来实现上述需求:

javascript 复制代码
<el-button type="primary" plain size="mini" @click="handleSelectAll">全部选中</el-button>
<el-table
      ref="tableRef"
      :data="tableData"
      @selection-change="handleSelectionChange"
      :row-key="row => row.id"
>
      <el-table-column type="selection" reserve-selection label="序号" />
      <el-table-column label="编号" prop="code" />
</el-table>
export default {
	methods: {
		/** 多选框选中操作 */
	    handleSelectionChange(selection) {
	      this.ids = selection.map((item) => item.id);
	    },
	    // 全部选中
	    handleSelectAll() {
	      getAllTableIds().then(res => {
	        this.ids = res.data
	        this.setSelectedCheckbox()
	      })
	    },
	    // 设置按勾选框选中
	    setSelectedCheckbox() {
	      this.$nextTick(() => {
	        if (this.ids.length > 0) {
	          this.tableData.forEach((item) => {
	            if ( this.ids.includes(item.id) ) {
	              this.$refs.tableRef.toggleRowSelection(item, true);
	            }
	          });
	        }
	      })
	    },
	}
}

存在问题

你这样写了之后,感觉还不错,点击全部选中按钮,也确实全都勾选了,就像上图一样,但是当你切换到第二页时,你就傻眼了,咋没勾选上呢?

问题分析

上面我们的思路主要分为以下几个步骤:

  • 点击按钮,从接口处获取全部id列表,并保存到ids数组变量

  • 遍历当前页的数据,如果ids中存在该id,那么就把当前行设置为勾选状态

  • 切换分页时也调用setSelectedCheckbox方法

  • 傻眼了
    其实,逻辑都没有错,错的是没用对方法,就是上面提到的selection-change方法,如果你对该方法的函数handleSelectionChange打印一下,你会发现该方法执行了10次(因为每页10条数据)
    因为你在循环中执行勾选:

    javascript 复制代码
    this.$refs.tableRef.toggleRowSelection(item, true);

    就不断地触发handleSelectionChange方法,这也导致上面给ids赋值全部id的集合,也会变为当前页的集合,也就导致当你切换分页时,第二页不会勾选的原因。

解决方案

el-table文档中还有这两种方法

既然循环勾选的时候会触发selection-change的方法,那么我们不用这个方法不就好了吗。

监听表格变化,可以用select和select-all两种方法的结合;因为勾选状态无非就是勾选单行和勾选当前页两种嘛!

改进思路如下

  • 点击按钮,从接口处获取全部id列表,并保存到ids数组变量
  • 遍历当前页的数据,如果ids中存在该id,那么就把当前行设置为勾选状态
  • 切换分页时也调用setSelectedCheckbox方法
  • 单行勾选变化
    • 选中:把该行id值push进ids数组,并去重(防止以外情况)
    • 取消勾选:把该行id值从ids数组中去除
  • 当前页勾选变化
    • 选中:把当前页的id值push进ids数组,并去重(防止以外情况)
    • 取消勾选:把当前页的id值从ids数组中去除

这样就不会影响ids的值了!

具体代码实现如下

javascript 复制代码
<el-button type="primary" plain size="mini" @click="handleSelectAll">全部选中</el-button>
<el-table
      ref="tableRef"
      :data="tableData"
      @select="handleSelectRow"
      @select-all="handleSelectAllRow"
      :row-key="row => row.id"
>
      <el-table-column type="selection" reserve-selection label="序号" />
      <el-table-column label="编号" prop="code" />
</el-table>
export default {
	methods: {
		/** 多选框选中操作 */
	    handleSelectionChange(selection) {
	      this.ids = selection.map((item) => item.id);
	    },
	    
	    // 选择某行
	    handleSelectRow(selection, row) {
	      const id = row.id
	      if(this.ids.includes(id)) {
	        this.ids = this.ids.filter(item => item !== id)
	      } else {
	        this.ids.push(id)
	      }
	    },
	
	    // 选择当前页
	    handleSelectAllRow(selection) {
	      // 如果全部勾选
	      if(selection.length > 0) {
	        const ids = selection.map((item) => item.id);
	        this.ids = Array.from(new Set([...this.ids,...ids]))
	      } else {
	        // 如果当前页取消勾选
	        const ids = this.tableData.map((item) => item.id);
	        this.ids = this.ids.filter(item => !ids.includes(item))
	      }
	    },
	    
	    // 设置按勾选框选中
	    setSelectedCheckbox() {
	      this.$nextTick(() => {
	        if (this.ids.length > 0) {
	          this.tableData.forEach((item) => {
	            if ( this.ids.includes(item.id) ) {
	              this.$refs.tableRef.toggleRowSelection(item, true);
	            }
	          });
	        }
	      })
	    },
	}
}

这样就能解决一键全选、且分页保留勾选状态的功能了!

别忘了,请求列表接口时也调用setSelectedCheckbox方法

如果有更好的解决办法,可在评论区讨论,谢谢。

相关推荐
小poop5 小时前
CSS 基础与实战:从入门到精通网页美化
前端
Csvn7 小时前
运行时性能
前端
Never_every998 小时前
位图转矢量工具哪个好?实测抠抠图AI位图转矢量工具
大数据·前端
paopaokaka_luck8 小时前
宠物门店经营管理系统(销售与库存联动、进货自动记账、 退换与退款关联、员工个人业绩、ECharts 经营分析、滞销识别与客户分层、宠物档案年龄计算)
前端·javascript·spring boot·mysql·echarts·mybatis·1024程序员节
空中湖9 小时前
用 React 写数据大屏:为什么我不建议用图表库
前端·react.js·前端框架
欣欣之王来了10 小时前
原始HTML插值:v-html指令的使用与安全风险
前端·学习·架构·项目·vue3教程
IT_陈寒10 小时前
Redis的LRU淘汰策略坑了我一整天
前端·人工智能·后端
计算机魔术师10 小时前
砍半价格、参数再涨,国产旗舰追到 Opus 鼻尖了
前端
paopaokaka_luck10 小时前
心理咨询管理系统(WebSocket实时沟通、基于用户的协同过滤、 ECharts多维分析、 预约业务流程、预约校验与定时处理)
java·vue.js·spring boot·mysql·spring·echarts·1024程序员节
特立独行的猫A10 小时前
10 MB 的桌面 AI 客户端:用仓颉 + 系统 WebView 替代 Electron
前端·harmonyos