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

前前言

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

什么,你还不会 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>
相关推荐
「、皓子~25 分钟前
后台管理系统的诞生 - 利用AI 1天完成整个后台管理系统的微服务后端+前端
前端·人工智能·微服务·小程序·go·ai编程·ai写作
就改了28 分钟前
Ajax——在OA系统提升性能的局部刷新
前端·javascript·ajax
凌冰_30 分钟前
Ajax 入门
前端·javascript·ajax
京东零售技术1 小时前
京东小程序JS API仓颉改造实践
前端
奋飛1 小时前
TypeScript系列:第六篇 - 编写高质量的TS类型
javascript·typescript·ts·declare·.d.ts
老A技术联盟1 小时前
从小白入门,基于Cursor开发一个前端小程序之Cursor 编程实践与案例分析
前端·小程序
风铃喵游1 小时前
构建引擎: 打造小程序编译器
前端·小程序·架构
sunbyte1 小时前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | ThemeClock(主题时钟)
前端·javascript·css·vue.js·前端框架·tailwindcss
小飞悟1 小时前
🎯 什么是模块化?CommonJS 和 ES6 Modules 到底有什么区别?小白也能看懂
前端·javascript·设计
浏览器API调用工程师_Taylor1 小时前
AOP魔法:一招实现登录弹窗的全局拦截与动态处理
前端·javascript·vue.js