表格?跨页选择?还要搜索和修改每页?

前前言

写完之后才发现已经有人写了类似的实现了。。。

什么,你还不会 vue 表格跨页多选?

嗨呀(摊手)

不过测试了一下 这个实现方案 有一个局限就是没法响应toggleRowSelection的选择。哈!

不过人家的文章确实写的好哇,学习了学习了。

前言

因为业务中经常遇到需要做表格的跨页选择的需求;但element-ui并不具备相应的功能,所以封装了一个比较通用(不限于element-ui)的工具类来实现。

需要考虑的点

  • 表格有多页且可以切换,需要在已选数据出现的时候,重新勾选上。
  • 表格每页数量可以修改,也需要搜索过滤的功能,所以用页码映射的方式并不可行。

原理

element-ui 表格的 selection-change 事件只会返回当前页的已选值。

即使对比新旧已选的两个数组,也无法确定在新数组中缺失的元素是因为跨页还是因为被取消选中。

核心思路的根据 表格 的 selection-change 事件只会返回当前页所有已选数据的特性。

  • 在切页前后,将【当前页的已选值】从【所有已选值】的map中弹出,放到【编辑中】的map中。

  • 在选择时 selection-change的事件监听处理函数中,把入参的当前页是所有已选值转换成map并赋值给【编辑中】的map。

  • 在切页前将【编辑中】map的值塞入【所有已选值】的map中。

特殊说明:为了便于查询,表格数据转的map都使用id作为key,所以需要保证数据项都有一个唯一的id值。

工具类的实现

js 复制代码
  class TableCrossPageSelectHelper {
    constructor({
      getTableData = () => [], // 获取表格数据的方法
      setInSelected = () => ({}), // 将选中状态写入的方法
    } = {}) {
      this.selectingTableMap = {}; // 当前页选中中的map
      this.selectedTableMap = {}; // 其他页已选的map
      this.getTableData = getTableData;
      this.setInSelected = setInSelected;
    }
    // 获取所有可选值
    getAllSelectedData() {
      return Object.values({ ...this.selectingTableMap, ...this.selectedTableMap });
    }
    // 把当前页数据从已选map中弹出,放到选择中的map
    popCurrentPageSelectedData() {
      this.getTableData().forEach(d => {
        if (!this.selectedTableMap[d.id]) return;
        // element-ui可以注释掉这行 
        // 因为调用toggleRowSelection方法的时候,对应的select-change事件会被触发
        this.selectingTableMap[d.id] = d;
        
        delete this.selectedTableMap[d.id];
        this.setInSelected(d)
      });
    }
    pushCurrentPageSelectingData() {
      Object.assign(this.selectedTableMap, this.selectingTableMap);
      // element-ui可以注释掉这行,table数据切换的时候自己会触发select-change事件 
      // 从而在updateSelectingTableMap清空
      this.selectingTableMap = {};
    }
    // 记录当前页的已选值
    updateSelectingTableMap(selectedDataList) {
      this.selectingTableMap = selectedDataList.reduce((map, d) => {
        map[d.id] = d;
        return map;
      }, {});
    }
  }

demo

js 复制代码
<template>
  <div>
    <el-table
      ref="multipleTable"
      :data="tableData"
      tooltip-effect="dark"
      style="width: 100%"
      @selection-change="onSelectionChange"
    >
      <el-table-column type="selection" width="55"> </el-table-column>
      <el-table-column label="日期" width="120">
        <template slot-scope="scope">{{ scope.row.date }}</template>
      </el-table-column>
      <el-table-column prop="name" label="姓名" width="120"> </el-table-column>
      <el-table-column prop="address" label="地址" show-overflow-tooltip>
      </el-table-column>
    </el-table>
    <button @click="loadData">切页</button>
  </div>
</template>

<script>

import TableCrossPageSelectHelper from './TableCrossPageSelectHelper' 

export default {
  name: 'TableText',
  data() {
    return {
      tableData: [],
      tableCrossPageSelectHelper: new TableCrossPageSelectHelper(),
      tableData1: [
        {
          id: '1',
          date: '2016-05-03',
          name: '页面一-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
        {
          id: '2',
          date: '2016-05-02',
          name: '页面一-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
        {
          id: '3',
          date: '2016-05-04',
          name: '页面一-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
        {
          id: '4',
          date: '2016-05-01',
          name: '页面一-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
        {
          id: '5',
          date: '2016-05-08',
          name: '页面一-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
        {
          id: '6',
          date: '2016-05-06',
          name: '页面一-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
        {
          id: '7',
          date: '2016-05-07',
          name: '页面一-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
      ],
      tableData2: [
        {
          id: '8',
          date: '2016-05-03',
          name: '页面二-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
        {
          id: '9',
          date: '2016-05-02',
          name: '页面二-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
        {
          id: '10',
          date: '2016-05-04',
          name: '页面二-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
        {
          id: '11',
          date: '2016-05-01',
          name: '页面二-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
        {
          id: '12',
          date: '2016-05-08',
          name: '页面二-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
        {
          id: '13',
          date: '2016-05-06',
          name: '页面二-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
        {
          id: '14',
          date: '2016-05-07',
          name: '页面二-王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        },
      ],
    };
  },
  methods: {
    onSelectionChange(selectedDataList) {
      this.tableCrossPageSelectHelper.updateSelectingTableMap(selectedDataList);
    },
    queryData() {
      return Promise.resolve(
        this.tableData === this.tableData1 ? this.tableData2 : this.tableData1
      );
    },
    loadData() {
      // 切页前将数据推入
      this.tableCrossPageSelectHelper.pushCurrentPageSelectingData();
      this.queryData()
        .then(res => {
          this.tableData = res;
        })
        .then(() => {
          // 这里要延后处理,保证时机在table清空旧已选值之后
          setTimeout(() => {
            this.tableCrossPageSelectHelper.popCurrentPageSelectedData();
          }, 100);
        });
    },
  },
  mounted() {
    this.loadData();
    this.tableCrossPageSelectHelper = new TableCrossPageSelectHelper({
      getTableData: () => this.tableData,
      setInSelected: (d) => this.$refs.multipleTable.toggleRowSelection(d, true),
    });
  },
};
</script>

<style lang="less" scoped></style>
相关推荐
长天一色8 分钟前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_23426 分钟前
npm、yarn、pnpm之间的区别
前端·npm·node.js
秋殇与星河28 分钟前
CSS总结
前端·css
NiNg_1_23428 分钟前
Vue3 Pinia持久化存储
开发语言·javascript·ecmascript
读心悦29 分钟前
如何在 Axios 中封装事件中心EventEmitter
javascript·http
BigYe程普1 小时前
我开发了一个出海全栈SaaS工具,还写了一套全栈开发教程
开发语言·前端·chrome·chatgpt·reactjs·个人开发
神之王楠1 小时前
如何通过js加载css和html
javascript·css·html
余生H1 小时前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
程序员-珍1 小时前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发
axihaihai1 小时前
网站开发的发展(后端路由/前后端分离/前端路由)
前端