vue中table实现真正的跨越全选

目录
  • 一、项目需求
  • 二、代码实现
  • 三、代码实现全选按钮的半选状态
  • 四、总结

一、项目需求

1.最初产生

运营测试时,提出跨页全选的要求;感官上在页面中只要勾选上方的复选框,那么就要勾选所有的数据。需求大致描述如下:

image.png

2.实现思路:

2.1 翻找element-ui框架文档及网上的实现方式:全选勾选的本页的数据,只有翻页时才会勾选下一页的数据;当翻到非首页,勾选全选按钮,得到的效果也不会选中前面页面的数据等等。
2.2 框架本身的限制,全选并不会拿到所有的数据,另外考虑到数据过多的情况,前端传递所有选中id不太现实;那么就实现感官上的全选,只要点击全选,页面效果是【全勾选所有】数据。

二、代码实现

第一步:去除项目本身的全选按钮,添加属于自己的【全选】按钮

<template>
    <div class="change-table">
        <el-checkbox 
        :class="allChangeFlag ? 'change-nocheckbox' : 'change-checkbox'"  
        v-model="checkChangeAll"
        @change="handleCheckAllChange"
        :disabled="!tableData.length"
        ></el-checkbox>
        <el-table
          border
          ref="tableData"
          :data="tableData"
          style="width: 100%"
          max-height="750"
          :row-key="getRowKeys"
          @select="changeSelect"
          @select-all="changeSelectAll"
          @selection-change="handleSelectionChange"
        >
          <el-table-column
            type="selection"
            :reserve-selection="true"
            width="55"
            align="center"
          ></el-table-column>
          <el-table-column
            type="index"
            :index="
              (index) => indexrank(index, this.pageNum, this.pageCount)
            "
            label="序号"
            width="55"
          ></el-table-column>
          <el-table-column
            label="操作"
            fixed="right"
            width="140"
            align="left"
          >
            <template v-slot="scope">
              <el-button
                type="text"
                class="operat-btn"
                @click="getDetail(scope.row)"
              >
                查看详情
              </el-button>
              <el-button
                v-if="scope.row.back_flag"
                type="text"
                class="operat-btn"
                @click="openDialog('recall', scope.row, scope.$index)"
              >
                撤回
              </el-button>
            </template>
          </el-table-column>
        </el-table>
        <div class="pagination">
          <page
            :total="totalNum"
            :page="pageNum"
            :size="pageCount"
            :Slzes="[5, 10, 20, 50]"
            @handlePageSizeChange="handleChange"
          ></page>
        </div>
      </div>
</template>

第二步:隐藏el-table的全选按钮,定位自定义el-checkbox

// 样式代码
<style>
 .change-table {
   position: relative;
 }
.change-checkbox {
  position: absolute;
  left: 21px;
  top: 20px;
  z-index: 10;
}
.change-checkbox >>> .el-checkbox__input.is-checked .el-checkbox__inner,
.el-checkbox__input.is-indeterminate .el-checkbox__inner {
  background: #fff;
  border-color: #dcdfe6;
}
.change-nocheckbox {
  position: absolute;
  left: 21px;
  top: 21px;
  z-index: 10;
}
.change-nocheckbox >>> .el-checkbox__inner::after {
  border: none;
}
::v-deep .el-table .disabledCheck .cell .el-checkbox__inner {
  display: none;
}
</style>

第三步:监听数据,配合UI库规定方法或属性,实现感官全选

<script>
export default {
 data() {
    return {
     tableData:[],
     allChangeFlag: false, // 是否勾选自定义全选按钮
     checkChangeAll: false, // 自定义全选标识
     unmultipleSelection: [], // 未选中数据数组
     enterUnCheckedPk: [], // 选中数据pk数组
     isTableAll: false, // table组件有无点击全选按钮标识
     checkVal: [], // 选中数据数组
     enterCheckedPk: [], // 选中数据pk数组
    }
 },
 watch:{
 // 监听渲染列表数组的变化,一旦变化 执行相关函数,使全选状态下,每一页按照全选显示
    tableData: {
      handler(value) {
        if (this.isTableAll) {
          let that = this;
          let len = that.checkVal.length;
          let lenOff = that.unmultipleSelection.length;
          value.forEach((row) => {
            // 遍历新请求回来的当页数据,和已经选择的数组中所有对象对比,如果有相同的,说明已经选择了,不再选择,其他没有选择的设置为选中状态
            for (let i = 0; i < len; i++) {
              if (row.pk_info_manage === that.checkVal[i].pk_info_manage) {
                that.$refs.tableData.toggleRowSelection(row, false);
                break;
              } else {
                that.$refs.tableData.toggleRowSelection(row, true);
              }
            }
            // 循环遍历新的请求回来的当页数据,和手动未选择的数组对比,如果有相同的,将其样式显示为未选择状态
            for (let i = 0; i < lenOff; i++) {
              if (
                row.pk_info_manage ===
                that.unmultipleSelection[i].pk_info_manage
              ) {
                that.$refs.tableData.toggleRowSelection(row, false);
              }
            }
          });
        }
      },
      deep: true,
    },
    // 跨页选择
    checkVal: {
      handler(newValue, old) {
        this.$nextTick(() => {
          if (newValue.length > 0) {
            if (this.totalNum != newValue.length) {
              this.$refs.tableData.store.states.isAllSelected = false;
            } else {
              this.checkChangeAll = true;
              this.$refs.tableData.store.states.isAllSelected = true;
            }
          } else {
            this.$refs.tableData.clearSelection();
          }
        });
      },
    },
    // 监听未选中的数据变化,如果存在则全选数据不为全选
    unmultipleSelection: {
      handler(newValue, old) {
        this.enterUnCheckedPk = [];
        this.$nextTick(() => {
          this.unmultipleSelection.forEach((item) => {
            if (this.enterUnCheckedPk.indexOf(item.pk_info_manage) == -1) {
              this.enterUnCheckedPk.push(item.pk_info_manage);
            }
          }); // 获取未选中的pk
        });
      },
    },
 },
 methods:{
    // 跨页选择 给table每个添加不同的key
    getRowKeys(row) {
      return row.pk_info_manage;
    },
    // 勾选自定义复选框方法
    handleCheckAllChange() {
      this.allChangeFlag = !this.allChangeFlag;
      this.unmultipleSelection = []; // 取消选中数据
      this.enterUnCheckedPk = []; // 取消选中数据pk
      this.checkVal = []; // 选中数据
      this.enterCheckedPk = []; // 选中数据pk
      this.changeSelectAll();
    },
    changeSelect(selection, row) {
      if (this.isTableAll) {
        let selected = selection.length && selection.indexOf(row) !== -1; // 为true时选中,为 0 时(false)未选中
        // 当手动操作为未选中状态时
        if (!selected) {
          // 将未选中的数据放在一个变量里
          this.unmultipleSelection.push(row);
          // 当再次手动操作为选中状态的时候
        } else {
          // 为了使再次选中后,将未选择数组中的该数据删除掉,遍历未选择的数组 和当前操作打√的数据比较,如果不同的就过滤留下,相同的就去除。
          this.unmultipleSelection = this.unmultipleSelection.filter(
            // 如果item.score不等于row.score就留下
            (item) => item.pk_info_manage !== row.pk_info_manage,
          );
        }
      } else {
        this.unmultipleSelection = [];
      }
    },
    // el-table全选方法
    changeSelectAll(val) {
      if (!this.isTableAll) {
        // 1.1.1遍历当前展示的数组,使所有的多选框为 √ 选择状态
        this.tableData.forEach((row) => {
          this.$refs.tableData.toggleRowSelection(row, true);
        });
        this.isTableAll = true;
        // 1.2当选择所有 选项框状态为 空 时
      } else {
        this.isTableAll = false;
        // 1.2.1遍历当前展示的数组,使所有的多选框为 未 选择状态
        this.$refs.tableData.clearSelection();
      }
    },
     // 复选框选择
    handleSelectionChange(val) {
      this.checkVal = val;
      this.enterCheckedPk = [];
      this.checkVal.forEach((item) => {
        if (this.enterCheckedPk.indexOf(item.pk_info_manage) == -1) {
          this.enterCheckedPk.push(item.pk_info_manage);
        }
      });
    },
 }
}
</script>

三、代码实现全选按钮的半选状态

image.png

半选实现的思路:

  • 未点击过全选:每次勾选数据即为半选;
  • 勾选全选:监听未勾选的数据,只要存在未勾选数据,即为半选。
// 此处代码为单纯半选状态的处理
<el-checkbox 
    :class="allChangeFlag ? 'change-nocheckbox' : 'change-checkbox'"  
    v-model="checkChangeAll"
    @change="handleCheckAllChange"
    :disabled="!tableData.length"
    :indeterminate="isIndeterminate"
></el-checkbox>
data(){
 return {
   isIndeterminate: false, // 半选状态标识
 }
},
watch: {
    // 跨页选择
    checkVal: {
      handler(newValue, old) {
        this.$nextTick(() => {
          if (newValue.length > 0) {
            if (this.totalNum != newValue.length) {
              if(!this.checkChangeAll) {
                this.isEnterpriseIndeterminate = true; // 在未勾选全选,手动操作时,再控制半选状态
              }
              this.$refs.tableData.store.states.isAllSelected = false;
            } else {
              this.checkChangeAll = true;
              this.$refs.tableData.store.states.isAllSelected = true;
            }
          } else {
            this.$refs.tableData.clearSelection();
          }
        });
      },
    },
    // 监听未选中的数据变化,如果存在则全选数据不为全选
    unmultipleSelection: {
      handler(newValue, old) {
        this.$nextTick(() => {
          this.isIndeterminate = newValue.length > 0; // 控制半选状态
        });
      },
    },
}

四、总结

实现跨页全选,本质上仍然是前后端配合的,全选标识flag、勾选或未勾选pks、查询的参数searchParams

  • 如果是全选的话,需要前后端配合,设置全选标识flag:true,传递全选情况下的查询条件:searchParams;
  • 全选但取消勾选个别几项,设置全选标识flag: true,传递查询条件searchParams、取消勾选的pk值:pks;
  • 若是正常勾选数据,进行数据操作,设置全选标识flag:false,选中勾选的pk值:pks。

到此这篇关于vue中table实现真正的跨越全选的文章就介绍到这了,更多相关vue table跨越全选内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

您可能感兴趣的文章:

  • vue实现全选、反选功能
  • 使用vue.js实现checkbox的全选和多个的删除功能
  • 利用Vue.js实现checkbox的全选反选效果
  • 利用Vue.js指令实现全选功能
  • vue实现全选功能
  • vue.js实现的全选与全不选功能示例【基于elementui】
  • vue实现全选和反选功能
  • vue使用监听实现全选反选功能
  • vue 实现全选全不选的示例代码

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注