废话不多说,着急解决问题的直接看,后面会解释
1.拿到回显的id数组
//我这写得简单,意思一下,你们自己要回显,肯定能拿到
async created() {
if (this.editBox.status === "add") {
...
} else {
...
this.selectIds = this.editBox.selectIds
...
}
},
2.写一个回显方法
// tableData 数组列表
// selectIds 选中id的数组
// multipleTable el-table的ref
// toggleRowSelection el-table的回显选中方法
// 回显多选
echo() {
this.$nextTick(() => {
this.tableData.forEach(row => {
if (
this.selectIds &&
this.selectIds.length !== 0
) {
if (this.selectIds.includes(row.id)) {
this.$refs.multipleTable.toggleRowSelection(
row,
true
);
}
}
});
});
},
3. 在获取tabelData数据的方法里调用
// 请求参数,带分页的
//queryParams {
// pageNum: 1,
// pageSize: 10
//}
//获取列表方法
async getTableList() {
this.loading = true;
let response = await listTabel(this.queryParams);
this.tableData = response.rows;
this.total = response.total;
this.loading = false;
this.echo();
},
基本带分页的回显能完成了,业务暂时能交差。
但是到这一步还没有完,需要进一步优化,但在优化之前,讲一下避坑点和优化点
避坑点:不要用form表单中存选中id数组的字段,存放我们的回显id数组
async created() {
if (this.editBox.status === "add") {
...
} else {
...
this.selectIds = this.editBox.selectIds
// 不要为了图简单进行下述操作
this.form.ids = this.selectIds
...
}
},
首先,el-table提供的toggleRowSelection方法,有点坑,拿elementUI官方示例举例。
回显选中时,它会调用@selection-change绑定的方法来进行选中操作。而我们在实现选中这个业务需求时,肯定会用到这个方法来做一些处理。例如,拿到所有选中项的id组成数组,传给后端
// 简单举个例子,真实业务可能更复杂
handleSelectionChange(val) {
let ids = [];
val.forEach(item => {
ids.push(item.id);
});
this.form.ids = ids
}
这会出现什么问题呢?
比如我们的选中回显id数组为 [1,2,3,4,21,22,51,52]
而我们的分页参数pageNum:1,pageSize:10
查到的10条数据 id 从1-10 递增
回显的时候调用该方法,他只能回显id为1,2,3,4的项,其他找不到。这个时候执行
this.form.ids = ids
就会把新数组 [1,2,3,4] 覆盖掉旧数组 [1,2,3,4,21,22,51,52]
那么其他页的选中项就永远回显不出来
优化点:回显的选中项,给取消掉,切换到table另一页,在切换回来,回显的选中项依然存在。
为什么呢?因为存放我们选中操作的 form.ids 没有和 selectIds 关联起来。
上面的避坑点讲了,直接使用赋值操作关联起来是不行的,并且el-table提供的toggleRowSelection方法会调用@selection-change绑定的方法来执行选中操作,那要怎么关联呢?
找规律。
举例子 数组a是我们存放选中id数组的地方;数组b是我们的回显id数组 。
b 假设有固定值为 [1,2,3,7,8]
a 一开始空数组 []
情况1:a选中有,b也有,那么b不需要变
a为 [1] , b 为 [1,2,3,7,8]
a为 [1,2] , b 为 [1,2,3,7,8]
a为 [1,2,3] , b 为 [1,2,3,7,8]
情况2:a选中有,b没有,那么b需要新增
a为 [1,2,3,4] , b 为 [1,2,3,7,8,4]
a为 [1,2,3,4,5] , b 为 [1,2,3,7,8,4,5]
情况3:a取消选中,b有,那么b需要删除该元素
a为 [2,3,4,5] , b 为 [2,3,7,8,4,5]
a为 [2,3,4] , b 为 [2,3,7,8,4]
得出什么规律呢,new a 和 old a 比较,得到新增的元素或者缺少的元素,这个元素如果数组b有,新增的情况下,b不需要动,缺少的情况下,b需要删除该元素。这个元素如果数组b没有,新增的情况下,b也需要新增,缺少的情况下,b不需要动。
new、old 直接想到watch监听,监听form.ids
优化方法
watch: {
"form.ids": {
handler(newVal, oldVal) {
console.log("newVal", newVal);
console.log("oldVal", oldVal);
// 有两种情况需要排除掉
// oldVal == undefined 因为初次监听 oldVal肯定是没有值的,为undefined
// oldVal == this.selectIds.join(",")
// 因为el-table提供的toggleRowSelection方法会调用
// @selection-change绑定的方法来执行选中操作的缘故,
// 所以第二次监听,oldVal 和 this.selectIds 相等
if (
oldVal == undefined ||
oldVal == this.selectIds.join(",")
) {
return;
}
let b = this.selectIds;
// 由于我这边业务需求,我的form.ids存的是逗号相隔的字符串,所以我需要多一步操作
function stringToArray(str) {
if (str === "") return [];
return str.split(",").map(Number);
}
let newA = stringToArray(newVal);
let oldA = stringToArray(oldVal);
// 创建 Set 用于快速查找
let newASet = new Set(newA);
let oldASet = new Set(oldA);
// 找到 newA 中有但 oldA 中没有的元素 (新增元素)
for (let elem of newA) {
if (!oldASet.has(elem)) {
if (!b.includes(elem)) {
b.push(elem);
}
}
}
// 找到 oldA 中有但 newA 中没有的元素 (删除元素)
for (let elem of oldA) {
if (!newASet.has(elem)) {
if (b.includes(elem)) {
b = b.filter(e => e !== elem);
}
}
}
this.selectIds = b;
},
deep: true
}
}
结合前面的1,2,3点加上优化点,即可完美实现,子组件下,分页table的回显选中。