问题描述
首先,element-ui表格多选功能可以参考官网示例:表格数据多选;手动在表格中选取数据、通过监听selection-change获取选中项,实现起来非常顺利~
但在保存了选项、重新加载表格时,希望将已选项“打勾”却完全没有显示勾选状态:
debug过程
$nextTick
首先,遇事不决$nextTick!很多时候进行数据操作后页面显示不符合预期的问题,通过把数据操作放在$nextTick回调中就能得到解决!!具体原理可以参考:$nextTick原理深度解析
搭嘎内……并没有解决。。
在表格数据加载完成后再初始化选中项
本杂鱼反复捋顺自己封装的dataTable组件逻辑后,发现父级组件传来的选中项列表发生改变时,很可能表格数据还没有加载完成!因此实际上初始化选中项的时机应该在表格数据加载完成且父级选中项列表改变时!
也就是需要同时监听表格数据和父级选中项列表(同时监听多个属性可参考Vue watch如何同时监听多个属性?),且表格数据数量不少于选中项数量(表格数据加载完成了)再初始化选中项!
打没打内打没哟……Emm…但至少现在不是完全没有选中的效果了:
可以看到,具体的数据项还是没有勾选效果,但表头的全选框出现了半选效果!
表格选中项必须是表格数据的浅拷贝
本杂鱼有一个猜想,也许是父级传来的选中项列表有问题?于是直接用slice截取表格数据的前三项进行选中,发现no problem哒!但父级传来的选中项列表数据值明明和slice截取的一模一样,只是为了避免对象浅拷贝可能出现的问题(js深拷贝和浅拷贝的知识点可以参考JavaScript深浅拷贝区别),那是表格数据深拷贝得到的新数组……
哈哈哈!这次终于是解决啦!哦,我真的好dio★▽★
参考代码
此处贴出本杂鱼自己封装的el-table组件dataTable,仅供参考:
(还有一个有趣的知识点,强烈建议还不了解的小伙伴去看看嗷:vue透传)
<!-- 封装el-table -->
<template>
<div id="DataTable">
<div class="DataTable-table">
<el-table :ref="tableKey" :data="tableData" v-bind="tableConfig" v-on="$listeners" height="100%"
style="width: 100%;">
<el-table-column v-if="showSelection" type="selection" width="48" align="center"></el-table-column>
<el-table-column v-if="showNum" type="index" label="序号" width="80" align="center"></el-table-column>
<slot>
<el-table-column></el-table-column>
</slot>
</el-table>
</div>
<div v-if="showPagination" class="DataTable-pagination">
<el-pagination v-bind="tableConfig" v-on="$listeners" :page-sizes="pageSizes" :layout="pagiLayout"
:page-size.sync="query.pageSize" :total="total"></el-pagination>
</div>
</div>
</template>
<script>
export default {
name: 'DataTable',
inheritAttrs: false, // 透传属性、事件
props: {
tableKey: {
type: String,
default: () => 'dataTable'
},
// 表格配置
showSelection: { // 是否显示多选框
type: Boolean,
default: false
},
showNum: { // 是否显示序号
type: Boolean,
default: true
},
selectItems: { // 选中项列表(必须是表格数据的浅拷贝)
type: Array,
default: () => []
},
// 分页栏配置
showPagination: { // 是否显示分页栏
type: Boolean,
default: true
},
pageSizes: { // 分页大小
type: Array,
default: () => [10, 20, 50, 100]
},
pagiLayout: { // 分页栏布局配置
type: String,
default: () => 'total, prev, pager, next, sizes, jumper'
}
},
data () {
return {
tableData: [],
query: {
pageSize: 10
},
total: 100
}
},
computed: {
tableConfig () { // 属性透传
return {
stripe: true, // 默认显示表格条纹
...this.$attrs // 支持传过来的属性覆盖默认属性值
}
},
initSelection () { // 当表格数据或选中项发生改变时,重新初始化表格选中项
const { tableData, selectItems } = this
return { tableData, selectItems }
}
},
watch: {
initSelection: {
deep: true,
immediate: true,
handler (newVal) {
const { tableData, selectItems } = newVal
// 表格不支持选中数据、表格数据量少于选中的数据量(表格数据还没加载完)的情况下,不进行选中项初始化
if(!this.showSelection || tableData.length < selectItems.length) return
this.$nextTick(() => {
this.toggleSelection(selectItems)
})
}
}
},
mounted () {
},
methods: {
dataChange () { // 数据发生改变时触发
this.$emit('dataChange', this.tableData)
},
toggleSelection (selection) { // 切换给定列表项的选中状态
if (selection) {
this.$nextTick(() => {
selection.forEach(row => {
this.$refs[this.tableKey].toggleRowSelection(row)
})
})
} else {
this.clearSelection();
}
},
clearSelection () { // 清除全部选中项
this.$nextTick(() => {
this.$refs[this.tableKey].clearSelection()
})
}
}
}
</script>
<style lang="less" scoped>
#DataTable {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
.DataTable-table {
flex: 1;
overflow: auto;
.el-table::before {
background-color: transparent;
}
}
.DataTable-pagination {
position: relative;
left: 0;
bottom: 0;
height: 42px;
padding-top: 12px;
display: flex;
flex-direction: row-reverse;
}
}
</style>