vue3如何缓存element的table组件分页的选中数据,并进行回选?

在前端开发的过程中,表格是最常见的一种交互,而选择表格数据,批量操作也是业务中常出现的情景,例如,多选删除,多选商品创建订单等等。我们不可能用一个List来直接全部显示,会加大服务器压力与客户端显示压力,因此大多数情况下,我们都是通过表格分页进行展示的。这时候,就需要在不同的分页上选择数据,然后对所有选择的数据进行操作了。

思路

  1. 查询数据

    (1) 加载数据

    (2) 渲染数据

    (3) 回选

    (4) 重置取消选择的list

    (5) 当前选中数据初始化到当前页已选择列表)

  2. 在表格选中变化的时候,获取每一次增加或者取消选择的行(去重)

  3. 将新增的选择行与已经选择的项合并,根据唯一值去重(避免同一个数据来回添加)

  4. 从已选择的数据中,移除取消选择的数据

  5. 重置取消选择的list

代码解析

js 复制代码
// addList对象数组,根据id进行去重
addList.filter((item, index) => addList.findIndex((i) => i.id === item.id) === index)
js 复制代码
// 当前表格与当前表格选中的相进行对比,获取新增选择的数据
function getAddList() {
  return selection.filter((l) => !addSelect.value.find((i) => i.id === l.id));
}
js 复制代码
// 当前表格与当前表格选中的相进行对比,获取取消选择的数据
function getRemoveList() {
  return addSelect.value.filter((l) => !selection.find((i) => i.id === l.id));
}

完整代码

需要注意的是,本文代码中的isLoad,适用于判断当前页面有没有加载并回选完成,因为在表格使用toggleRowSelection的时候,会触发selection-change,所以等回选完成之后,再进行监听选择事件。

html 复制代码
<template>
  <el-table
    ref="tableRef"
    :data="tableList"
    @selection-change="selectionChange"
  >
    <el-table-column type="selection" label="选择" :width="60" />
    <el-table-column type="index" label="序号" :width="60" />
    <el-table-column prop="name" label="Name" />
  </el-table>
  <div class="text-right">
    <el-pagination
      layout="prev, pager, next"
      :total="50"
      @current-change="pageChange"
    />
  </div>
  <div>selectionList.length{{ selectionList.length }}</div>
  <div>{{ selectionList }}</div>
</template>

<script setup>
/**
 * 处理多页面选择数据集合的,两种方案
 * 方案一:每次页面或选项变化时候进行数据存取,逻辑处理列表(本篇代码实现这个)
 * 方案二:新增加选择历史纪录的列表,已选择的禁止再次选择,可通过历史选择纪录页面删除,再将历史纪录作为选择列表进行操作
 */
import { ref, onMounted, nextTick } from "vue";

onMounted(() => {
  nextTick(() => {
    loadData();
  });
});

const tableRef = ref();
const tableList = ref([]); // 当前表格数据
const pageNum = ref(1);
const isLoad = ref(false);

const addSelect = ref([]);
const removeSelect = ref([]);
const selectionList = ref([]);

// 页码变化
function pageChange(page) {
  pageNum.value = page;
  loadData();
}
// 加载当前页面数据
function loadData() {
  isLoad.value = false;
  tableList.value = []; // 模拟清除历史表格数据
  // 模拟生成表格数据
  for (let i = 0; i < 10; i++) {
    tableList.value.push({
      id: `${pageNum.value}_${i}`,
      name: `user_${pageNum.value}_${i}`,
    });
  }
  nextTick(() => {
    tableList.value.forEach((row) => {
      if (selectionList.value.find((o) => o.id === row.id)) {
        tableRef.value.toggleRowSelection(row, true);
      }
    });
    isLoad.value = true;
    removeSelect.value = [];
    addSelect.value = tableRef.value.getSelectionRows(); // 初始化当前页面选择数据,移除时候以这个参数为准
    // element-ui获取当前选择的数据可以使用this.$refs.tableRef.selection
    // 如果不行的话,可以使用selectionList(已选择的所有数据)和tableList(表格数据),取交集(百度方案很多)
  });
}

// 表格选择项变化时候触发
function selectionChange(selection = []) {
  if (!isLoad.value) return;
  // 当前表格与当前表格选中的相进行对比,获取新增选择的数据
  function getAddList() {
    return selection.filter((l) => !addSelect.value.find((i) => i.id === l.id));
  }
  const add = getAddList();
  const addList = [...addSelect.value, ...add];
  addSelect.value = addList.filter(
    (item, index) => addList.findIndex((i) => i.id === item.id) === index
  );
  // 当前表格与当前表格选中的相进行对比,获取取消选择的数据
  function getRemoveList() {
    return addSelect.value.filter((l) => !selection.find((i) => i.id === l.id));
  }
  const remove = getRemoveList();
  const removeList = [...removeSelect.value, ...remove];
  removeSelect.value = removeList.filter(
    (item, index) => removeList.findIndex((i) => i.id === item.id) === index
  );
  // 原选择的数据+新选择的数据
  let list = [...selectionList.value, ...addSelect.value];
  // 已选择的和新增的选择的项去重
  list = list.filter(
    (item, index) => list.findIndex((i) => i.id === item.id) === index
  );
  // 所有已经选择的项中,删除移除的项
  selectionList.value = list.filter(
    (o) => !removeSelect.value.find((i) => i.id === o.id)
  );
  // 移除删除的项之后,初始化待移除列表
  removeSelect.value = [];
}
</script>

<style lang="scss" scoped>
.text-right {
  display: flex;
  justify-content: flex-end;
}
</style>
相关推荐
黄尚圈圈21 分钟前
Vue 中引入 ECharts 的详细步骤与示例
前端·vue.js·echarts
浮华似水1 小时前
简洁之道 - React Hook Form
前端
正小安3 小时前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序
_.Switch5 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光5 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   5 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发
长路 ㅤ   5 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web5 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常5 小时前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式
莹雨潇潇6 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器