前前言
写完之后才发现已经有人写了类似的实现了。。。
嗨呀(摊手)
不过测试了一下 这个实现方案 有一个局限就是没法响应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>