el-talbe中的全选和翻页记忆功能
场景描述: 使用的是elementui, 一个列表dataList, 列表外有个群发按钮, 点击之后, 会在列表的最后一栏动态添加操作, 每行数据后面添加一个checkbox可以选择, 并且支持翻页记录,即第一页选择之后, 翻到第二页, 在回到第一页, 之前选中的还在.
这个是链接: elementui中的el-table elementui中的el-checkbox
前提:
- 列表的数据是分页获取的, 每次翻页都会重新获取.
- 最后的选择列是动态生成的, 不是一开始就有的.
- 列表页在路由中设置过缓存,几 meta: { keepAlive: true }
踩坑过程:
- el-table本身自带翻页缓存功能, 只需添加两个属性,即可是实现
// 关键代码
<el-talbe :data="dataList" ref="table" :row-key="(row)=>{return row.id}" @row-click="onRowClick" @selection-change="handleSelectionChange">
<el-table-column type="selectoin" :reserve-selection="true" />
</el-table>
// 在el-table中添加 :row-key 表示row的唯一值
// 在el-table-column 中添加 type="selectoin" :reserve-selection="true"
// @selection-change 返回已选的数据
// this.$ref.table.clearSelection()用于清楚所选
然而,理想很丰满, 显示很骨感
因为type="selection" 是动态生成的, 所以上述流程不生效.
-
可以考虑从数据处理方向入手
- 维护一份已选择的数据表arr,单独定义选择事件,
- 选中的时候添加到arr, 删除的时候,从arr删除,
- 每次翻页的时候比较, 比较当前数据(dataList)中有没有id在已选的arr中也存在的,如果有,则勾选, 没有,就不勾选.这里dataList和arr都是对象数组, 可能会比较复杂.
-
过程
- 从dataList获取的时候, 在每个元素上添加一个属性isChecked: false, 可在获取数据的方法中操作,或数据返回的接口中操作
- 动态添加一列, 绑定在checked
<el-table-column width="60px" label="操作" v-if="taskFlag"> <template slot-scope="scope"> <el-checkbox v-model="scope.row.checked" @click.prevent.stop.native="handleSelected(scope.row)" :disabled="!scope.row.class_id"></el-checkbox> </template> </el-table-column>
- 在点击事件中添加方法,处理arr数组的添加和删除
handleSelected(item) {
if(!item.class_id) return
item.checked = !item.checked
if(item.checked) {
this.selectedId.push(item)
}
if(!item.checked) {
var tempIndex = -1
this.selectedId.forEach((itemData, index) => {
console.log('itemData', itemData)
if(item.id == itemData.id) {
tempIndex = index
}
})
if(tempIndex === -1) {
console.log('没找到')
return
}
if(tempIndex > -1) {
console.log('删除')
this.selectedId.splice(tempIndex, 1)
}
}
},
+ 最后在监视页面的改变,可以watch dataList, 如果翻页,dataList就会改变, 然后比较dataList 和 arr 里面的数据, 判断每一行是否需要勾选
watch: {
dataList(val, old){
if(val.length) {
var data_arr = this.selectedId.map(item => {
return item.id
})
val.forEach(item => {
if(data_arr.indexOf(item.id) > -1) {item.checked = true}
})
}
}
},
-
结果 ~~ 又有一个坑
原因: 列表有点击事件, @row-click, 所以需要防止冒泡, 这里自然想到 .stop,
然而,@change.stop 会报错, 而官方文档没有提供@click方法, 但是原生的checkbox是存在的, 所以使用 @click.stop.native, 但是这个触发了另一个问题, 该方法会执行2次, 原因是el-checkbox的源码中, 有嵌套的组件都有@click事件, 此处具体没有深究, 并且也不能组织冒泡, 页面还是跳转了. 查资料后得知,这里要使用.prevent, 阻止默认行为, 这样就出现了上面哪个 @click.prevent.stop.native写法. 但是还是出现了新的问题, .prevent之后,会使 :disable失效, 虽然还是有disable的样式,(hover的时候显示 cursor: not-allowed) ,但是还是能选中, 需要给个不符合条件的直接return的逻辑. -
除了代码有点low, 功能是实现了,
-
接下来搞清楚 el-checkbox 中的源码, 为什么会有这些坑!!!