效果预览
实现思路
技术难点
1. 不能使用 selection-change 的原因
selection-change 的参数为当前页选中的所有行,在每次重新获取数据渲染表格时(如翻页时),参数为一个空数组,会导致历史选中的数据被清空!
即便使用 :reserve-selection="true"
来保留历史选中记录也无法达到预期效果。
2. toggleRowSelection失效的原因解析和解决方案
toggleRowSelection失效通常为以下两种情况:
(1)表格数据发生变化,表格还没渲染完便执行了toggleRowSelection
解决方案 : 在 $nextTick 中执行 toggleRowSelection
// toggleRowSelection 需在$nextTick中使用!
this.$nextTick(() => {
this.$refs.multipleTable.toggleRowSelection(row);
});
(2)toggleRowSelection的第一个参数不是表格源数据
即便数据的值完全一样也会失效,因为数据为引用类型,必须地址一样。
解决方案 :toggleRowSelection的第一个参数通过在表格数据中通过 find() 查找得到。
this.$nextTick(() => {
this.$refs.multipleTable.toggleRowSelection(
// 此处必须在 tableData 中查找对应的数据,否则 toggleRowSelection 会失效
this.tableData.find((row) => {
return row[this.UID] === item[this.UID];
}),
false
);
});
完整范例代码
<template>
<div class="mainBox">
<h3>已选择:h3>
<el-tag
:key="item[UID]"
v-for="(item, index) in selectedList"
closable
@close="removeItemByIndex(index, item)"
>
{{ item.name }}
el-tag>
<el-table
v-loading="loading"
ref="multipleTable"
:data="tableData"
@select="selectChange"
@select-all="selectAllChange"
>
<el-table-column type="selection" width="55" align="center">
el-table-column>
<el-table-column prop="ID" label="编号" align="center"> el-table-column>
<el-table-column prop="name" label="姓名" align="center">
el-table-column>
<el-table-column prop="age" label="年龄" align="center">
el-table-column>
el-table>
<el-row type="flex" class="pageBanner" justify="center">
<el-pagination
background
:total="total"
:page-size="pageSize"
@size-change="pageSizeChange"
@current-change="currentPageChange"
:current-page="currentPage"
:page-sizes="[1, 2, 3]"
layout="total, sizes, prev, pager, next, jumper"
>
el-pagination>
el-row>
div>
template>
<script>
export default {
data() {
return {
// 唯一标识符
UID: "ID",
loading: false,
total: 0,
pageSize: 3,
currentPage: 1,
selectedList: [
{
ID: 1,
name: "王小虎",
age: 10,
},
],
tableData: [],
};
},
mounted() {
// 页面初始化时,首次加载数据
this.getData(this.currentPage, this.pageSize);
},
methods: {
// 单行前的勾选状态切换
selectChange(selectedRows, row) {
// true为选中, 0或false为取消选中
let selected = selectedRows.length && selectedRows.indexOf(row) !== -1;
if (selected) {
this.addItem(row);
} else {
this.removeItem(row);
}
},
// 全选/取消全选
selectAllChange(selectedRows) {
let selectedMarkList = this.selectedList.map((item) => item[this.UID]);
// 当前页选中行的标记列表
let pageSelectedMarkList = Array.isArray(selectedRows)
? selectedRows.map((item) => item[this.UID])
: [];
this.tableData.forEach((row) => {
if (pageSelectedMarkList.includes(row[this.UID])) {
if (!selectedMarkList.includes(row[this.UID])) {
this.addItem(row);
}
} else if (selectedMarkList.includes(row[this.UID])) {
this.removeItem(row);
}
});
},
// 切换每页显示条数
pageSizeChange(newPageSize) {
this.pageSize = newPageSize;
this.getData(this.currentPage, this.pageSize);
},
// 切换页码--翻页
currentPageChange(newPage) {
this.currentPage = newPage;
this.getData(this.currentPage, this.pageSize);
},
// 更新勾选标记
updateMark() {
let selectedMarkList = this.selectedList.map((item) => item[this.UID]);
this.tableData.forEach((row) => {
if (selectedMarkList.includes(row[this.UID])) {
// toggleRowSelection 需在$nextTick中使用!
this.$nextTick(() => {
this.$refs.multipleTable.toggleRowSelection(row);
});
}
});
},
// 模拟访问接口获取数据
getData(page, pageSize) {
this.loading = true;
setTimeout(() => {
let data = [
{
ID: 1,
name: "王小虎",
age: 10,
},
{
ID: 2,
name: "张三",
age: 20,
},
{
ID: 3,
name: "李四",
age: 30,
},
{
ID: 4,
name: "何香",
age: 18,
},
{
ID: 5,
name: "刘刀",
age: 27,
},
{
ID: 6,
name: "关胜",
age: 33,
},
{
ID: 7,
name: "齐巧",
age: 55,
},
{
ID: 8,
name: "卢一方",
age: 45,
},
{
ID: 9,
name: "王兴海",
age: 66,
},
{
ID: 10,
name: "全德",
age: 100,
},
];
this.total = data.length;
let startIndex = pageSize * (page - 1);
let endIndex = pageSize * page;
this.tableData = data.slice(startIndex, endIndex);
this.updateMark();
this.loading = false;
}, 1000);
},
// 新增选中项
addItem(item) {
this.selectedList.push(item);
},
// 移除选中项
removeItem(item) {
for (let [index, itemTemp] of this.selectedList.entries()) {
if (itemTemp[this.UID] === item[this.UID]) {
this.removeItemByIndex(index);
break;
}
}
},
// 根据下标移除选中项
removeItemByIndex(index, item) {
this.selectedList.splice(index, 1);
// 若有item,则是点击标签上的关闭按钮,移除选中项
if (item) {
this.$nextTick(() => {
this.$refs.multipleTable.toggleRowSelection(
// 此处必须在 tableData 中查找对应的数据,否则 toggleRowSelection 会失效
this.tableData.find((row) => {
return row[this.UID] === item[this.UID];
}),
false
);
});
}
},
},
};
script>
<style scoped>
.mainBox {
margin: 30px;
}
.el-tag {
margin: 10px;
}
.pageBanner {
margin: 10px;
}
style>
化为己用
若你的唯一标识符不是 ID
,则修改 data() 中的UID 的值即可!
// 唯一标识符
UID: "ID",