【Vue2 + Element UI】 解决了关于el-table表格多选后,切换分页出现的多选状态回显不正确问题。请看详细解析!--前端

首先说一下我们出现的问题:

1、在初始化el-table表格和el-pagination分页,确保能将数据正常渲染出来后,分页功能页也没问题

2、然后我们进行全选和单选的操作,再点击分页进行切换,发现选中状态消失了...

3、为啥呢?

4、主要是因为默认情况下,在进行分页切换时不会保留之前页选中的状态。这是因为分页切换通常会重新加载新页的数据,从而导致之前页中的数据和选中状态都被清除了。

下面说下我们的解决思路:

1、首先我们需要把我们勾选的状态准确的保存下来

2、分页切换的时候会触发数据的加载,这时我们就需要去除之前存储的勾选状态

3、通过过滤筛选来将已勾选的状态回显到我们的el-table列表中

4、具体实现如下

第一节:代码部分,可直接创建新组件直接引用

部分关键变量和方法解析:      

 //mockjs为第三放插件,npm i mockjs 安装  ,用于前端生成随机数据时使用,对应下面getlist方法
 import Mock from 'mockjs' 

 //存储的勾选状态
 selectsdata:[] 
 
 //模拟接口,请求数据的方法       
 getlist() {

        return Mock.mock({ 'list|11-20': [{ 'name': '@cname', 'age|15-25': 0, 'city': '@city' }] }).list;

      }

 //el-table 回显的方法:  第一个参数回显行、第二个参数bool是否选中
 this.$refs.TabsRef.toggleRowSelection(dom,true)

全部代码:

<template>
    <div>
     <div style="display: flex;">
        <div style="width: 60vw;">
            <el-table
                ref="TabsRef"
                :data="currentPageData"
                border
                style="width: 100%;height: 600px;overflow: auto;"
                @select="selects"
                @select-all="selects"
                >
                <el-table-column
                    type="selection"
                    width="55">
                </el-table-column>
                <el-table-column
                prop="name"
                label="姓名"
                width="100">
                </el-table-column>
                <el-table-column
                prop="age"
                label="年龄"
                width="100">
                </el-table-column>
                <el-table-column
                prop="city"
                label="地址"
                width="200">
                </el-table-column>
            </el-table>
        </div>
        <div>
            <div>已选:</div>
            <span v-for="item in selectsdata">{{ `姓名:${item.name}` }}<br></span>
        </div>
     </div>
      <el-pagination
        background
        :hide-on-single-page="value"
        small
        :page-size="pageSize"
        layout="prev, pager, next"
        :total="arrs.length"
        @current-change="handleCurrentChange">
      </el-pagination>
    </div>
  </template>
  
  <script>
  //mockjs  npm安装   npm i mockjs
  import Mock from 'mockjs';
  
  export default {
    data() {
      return {
        arrs: [],
        currentPageData: [],
        value: false,
        pageSize: 10,
        currentPage: 1,
        selectsdata:[]
      };
    },
    methods: {
      getlist() {
        return Mock.mock({ 'list|11-20': [{ 'name': '@cname', 'age|15-25': 0, 'city': '@city' }] }).list;
      },
      //分页点击触发的
      handleCurrentChange(page) {
        this.currentPage = page;
        this.updateCurrentPageData();
        //这边要把回显的回显上去
        console.log('点击了分页,这个等会要回显,下面是回显的数据,看下对不对');
        console.log(this.selectsdata);
        if (this.$refs.TabsRef) {
            this.currentPageData.forEach((item,index)=>{
            // 当前页面的根据这个数组来回显 ,,this.selectsdata
              if (this.selectsdata.length>0) {
                //有回显的数据
                    let dom = this.selectsdata.find(items=>{
                       return items == item
                    })
                    if (dom) {
                        this.$nextTick(()=>{
                        this.$refs.TabsRef.toggleRowSelection(dom,true)
                        })
                 }
              }        
        })
        }
      },
      //这个方法类似🐟请求接口数据
      updateCurrentPageData() {
        const startIndex = (this.currentPage - 1) * this.pageSize;
        const endIndex = startIndex + this.pageSize;
        this.currentPageData = this.arrs.slice(startIndex, endIndex); //显示分页对应的
      },
      selects(selection, row) {
        if (this.selectsdata.length === 0) {
            console.log('第一次进来,没选,获取全不选的时候触发');
            this.selectsdata = selection;
        } else {
            if (this.selectsdata.length>0 &&!row) {
                console.log('点击全选/全不选',selection.length,this.selectsdata);
                // 然后修改 回显数据
                // this.currentPageData 是所有的数据
                if (selection.length>0) {
                    //全选了
                    console.log('全选');
                    this.currentPageData.forEach(item=>{
                        let find = this.selectsdata.find(selectedItem=>{
                           return selectedItem.name == item.name
                        })
                        if (!find) {
                            this.selectsdata.push(item)                           
                        }
                    })
                 }else{
                    console.log('全不选');
                    // 仅保留当前页数据中未选中的行
                    this.selectsdata = this.selectsdata.filter(item => {
                        // 检查当前行是否存在于当前页数据中
                        let find = this.currentPageData.find(pageItem => pageItem.name === item.name);
                        // 如果不存在,则保留该行
                        return !find;
                    });
                }
                return
            }else{
                console.log('单选');
                // 点击的时候有就删,没有就加
                const doms = this.selectsdata.find(item => item.name === row.name);
                // 如果点击的行已经存在于 selectsdata 中,则将其删除
                if (doms) {
                    this.selectsdata = this.selectsdata.filter(item => item.name !== row.name);
                } else {
                    // 如果点击的行不存在于 selectsdata 中,则将其添加到 selectsdata 中
                    this.selectsdata.push(row);
                }
            }
        }
      } 
    },
    created() {
      console.log('N组件');
      //这个arrs是所有的数据
      this.arrs = this.getlist();
      this.updateCurrentPageData();
    }
  };
  </script>
  
  <style>
  /* 这里可以添加样式 */
  </style>

注意: 

       代码不过多讲解了,主要看注释理解,几个地方用了判断都是为了区分不同的情况,比如

selection参数是选中的行的数组
row 只有在行内勾选的时候才会有的参数-用来判断是否全选

//全选和单选同的都是同一个方法,所以得区分开他们
//这里是判断是不是第一次选,如果勾选的没状态,就等于第一次选的  selection
if (this.selectsdata.length === 0) {
            console.log('第一次进来,没选,获取全不选的时候触发');
            this.selectsdata = selection;
        } else {
//通过!row来区分是全选还是全部选
                 if (this.selectsdata.length>0 &&!row) {
//全选内部通过全选的长度,要么为全部选==0 ,要么全选> 0                   
                           if (selection.length>0) { 
                    
                           }
                            else{
                           
                            }


                    }else{
                
                     }
                }

第二节:功能展示部分

初始化:

选中部分的行,右侧可以看到选中的行,为了让大家看到更加直观

第一页:

第二页:

此时我们分别在第一页和第二页各选中了2名,共4名,右侧可见,此时回到第一页查看回显效果

回显依然存在,接下来看全选/全不选

第二页全选,第一页去除两个,右边是对应的数据,后面操作就可以直接拿右侧数据了,OK

第三节:其他相关知识分享

1、一键展开关闭

【前端】- 在使用Element UI 的el-tree组件时,从底层去研究如何去实现一键展开/关闭【tree节点】的功能_el-tree 关闭展开-CSDN博客

2、vite + vue3项目的搭建

使用vite创建vue3项目 + 配置路由 + 配置pinia_vue3安装路由-CSDN博客

3、vite + vite 修改默认启动端口

【功能:vue3 + vite 修改默认启动端口】 - 以及相关配置详细解答,刚学习的小伙伴强烈推荐_vite设置端口-CSDN博客

祝 大 家 开 心 敲 代 码 、远 离 bug

  • 11
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值