效果预览
实现思路 data中定义 selectedList 数组保存选中的数据 在页面初次渲染、翻页、切换每页数据数量等每次重新获取表格数据渲染表格时,都根据 selectedList 勾选表格中已经选中的行 切换单行勾选状态时,判断是选中还是取消选中,选中则增加选中项,取消选中则移除选中项。 切换全选和取消全选时,根据当前页选中行的数据进行更新,若选中行已在 selectedList 中则不再重复添加,否则添加,对于其他非选中行若已在selectedList 中,则从 selectedList 中移除。 技术难点
-
不能使用 selection-change 的原因 selection-change 的参数为当前页选中的所有行,在每次重新获取数据渲染表格时(如翻页时),参数为一个空数组,会导致历史选中的数据被清空! 即便使用 :reserve-selection="true" 来保留历史选中记录也无法达到预期效果。
-
toggleRowSelection失效的原因解析和解决方案 toggleRowSelection失效通常为以下两种情况:
(1)表格数据发生变化,表格还没渲染完便执行了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 ); });
完整范例代码
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, item);
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
);
});
}
},
}, };
.mainBox { margin: 30px; } .el-tag { margin: 10px; } .pageBanner { margin: 10px; }