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

前前言

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

什么,你还不会 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>
相关推荐
C语言魔术师13 分钟前
【小游戏篇】三子棋游戏
前端·算法·游戏
小周不摆烂18 分钟前
探索JavaScript前端开发:开启交互之门的神奇钥匙(二)
javascript
匹马夕阳1 小时前
Vue 3中导航守卫(Navigation Guard)结合Axios实现token认证机制
前端·javascript·vue.js
你熬夜了吗?1 小时前
日历热力图,月度数据可视化图表(日活跃图、格子图)vue组件
前端·vue.js·信息可视化
我想学LINUX2 小时前
【2024年华为OD机试】 (A卷,100分)- 微服务的集成测试(JavaScript&Java & Python&C/C++)
java·c语言·javascript·python·华为od·微服务·集成测试
screct_demo2 小时前
詳細講一下在RN(ReactNative)中,6個比較常用的組件以及詳細的用法
javascript·react native·react.js
桂月二二8 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
CodeClimb9 小时前
【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
hunter2062069 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb9 小时前
web服务器 网站部署的架构
服务器·前端·架构