Vue + element 多选表格实现跨分页保存数据并回显
在大部分项目中如果存在数据的处理操作一般会有这样一个需求:多选表格因为数据太多,全选按钮需要从默认的全选当前页变为全选所有数据,并且每页记录的数据需要切换分页的时候保存下来并在切回分页的时候进行回显,这个时候我们就需要对 element ui 的表格进行一些处理elment ui 的 table 表格本身带了一个跨页保存数据的属性也就是说 row-key 配合 reserve-selection
-
应用场景:当用户在众多条数据中仅需要选择一部分数据进行操作的时候前端需要做的支持
需求背景:客户需要选择若干条数据进行存储,但由于数据众多进行了分页处理因此需要切换分页的时候保存之前已选的数据并进行回显,可以在任意一页点击(全选/取消全选)按钮,此时所有其他页面也相应全选或者非全选,默认所有数据全选状态。 -
大致思路:所有页面首先想到需求其次应该想到前后端交互,因为有全选状态,因此传递参数 id 组成的数组显然是不现实的,若数据成百上千条很容易造成内存泄漏,因此我们的思路是:增加一个全选标识,若用户点击全选 isAllChecked:true,ids:[] ,若用户点击全选之后取消几个不需要的数据:isAllChecked:true,ids:[1,2,3] 当全选为 true ids 有元素的时候,此时的 ids 是需要过滤掉的数据,当全选状态为 false ids 有元素的时候,此时 ids 是我们需要保存的数据 id
-
elment ui 的 table 表格本身带了一个跨页保存数据的属性
也就是说 row-key 配合 reserve-selection 是可以进行数据的保存的,我们可以通过请求到的数据和存储的跨页数据进行匹配做到回显不成问题,但是在我个人测试中虽然能实现数据保存和回显,但是跨页选择数据后全选按钮会出现问题,因为此时的全选状态只会在你请求的数据完全匹配你保存的数据的时候才会显示全选或者取消,否则都是半选中状态,举个例子:全选状态下切换分页到第二页,此时 reserve 保存的数据是两页的所有数据,你点击全选,此时应为取消全选状态,但是 table 在匹配数据的时候发现当前页取消的数据仅为 reserve 保存的一部分,此时的全选状态就变成了半选中状态而不是取消状态,这与需求不符暂时我没有找到优化办法,最终我放弃了 reserve-selection 配合 row-key 这个方案,
决定使用默认的表格全选取消来模拟实现上述需求。
- 这些是我们需要用到的内置函数
首先是全选的逻辑,我们需要一个全选表示 allDataFlag,还需要一个变量 dataLength 来保存请求到的数据长度来判断用户是否选中所有的数据,数组 multipleTable 用来存储选择的数据
selectAll(data) {
if (data.length == this.dataLength) {
this.allDataFlag = true
this.multipleTable = []
} else if(data.length == 0){
this.allDataFlag = false
this.multipleTable = []
}
},
我们在判断全选的时候来更改一下全选表示,并重置一下 multipleTable,因为当全选的时候我们不需要去传递所有数据 id 只需要传递 全选标识为 true 就行。
2. 接下来是点击每个 select 框触发的事件,因为我们传递的 ids 有不同的涵义 因此在这里我们首先需要判断用户点击的是勾选还是取消,下面是必要的逻辑代码,逻辑不难这里就不解释了就是分多种情况,当全选状态下点击取消选中状态的逻辑和非全选状态下点击选中或者取消的逻辑。
handleSelectionChange(val, row) {
//当前点击数据,是勾选还是取消
let selecteBool = val.length && val.indexOf(row) !== -1;
//若全选,则记录取消的数据;非全选,则记录选中的数据;
if (this.allDataFlag) {
if (!selecteBool) {
this.multipleTable.push(row)
} else {
if (this.multipleTable.length > 0) {
for (let i = 0; i < this.multipleTable.length; i++) {
if (row.id == this.multipleTable[i].id) {
this.multipleTable.splice(i, 1);//删除勾选的取消列表
}
}
}
}
} else {
if (selecteBool) {
this.multipleTable.push(row)
} else {
if (this.multipleTable.length > 0) {
for (let i = 0; i < this.multipleTable.length; i++) {
if (row.id == this.multipleTable[i].id) {
this.multipleTable.splice(i, 1);//删除已勾选列表中,再次取消的项;
}
}
}
}
}
},
- 最后一步就是对请求到的数据进行回显,原理就是根据保存的 id 进行循环判断请求到的数据是否包含,若包含则为之前选择的数据,在这里需要用到 el 的内置函数 toggleRowSelection 来对数据进行单独设置选中/取消状态
接下来我们只需要在请求成功之后的数据里进行回显操作就可以
this.$nextTick(()=>{
// 全选状态
if (this.allDataFlag) {
this.tableData.forEach((row) => {
this.$refs.MyTable.toggleRowSelection(row, true)
})
// 如果存在有之前取消的数据 进行取消展示
if (this.multipleTable.length > 0) {
this.tableData.forEach((item, i) => {
this.multipleTable.forEach((multItem, j) => {
if (this.tableData[i].id == this.multipleTable[j].id) {
this.$refs.MyTable.toggleRowSelection(this.tableData[i], false) //展示已取消的数据
}
})
})
}
}else {
// 非全选状态
// 如果存在有之前选中的数据 进行勾选展示
if (this.multipleTable.length > 0) {
this.tableData.forEach((item, i) => {
this.multipleTable.forEach((multItem, j) => {
if (this.tableData[i].id == this.multipleTable[j].id) {
this.$refs.MyTable.toggleRowSelection(this.tableData[i], true);//展示已勾选的数据
}
})
})
}
}
})
到这里所有逻辑就完成了,大家可以根据自己的实际情况来进行参考
更多推荐
所有评论(0)