最近碰到一个新的需求,先是需要获取用户组列表(做成表格),表格项可以展开,在展开的时候动态的获取所展开的用户组底下的用户列表。
问题描述
起初,我是把表格数据分开来,即外层用户组列表使用list
数组,内层嵌套的用户列表使用innerList
数组,两者互不干扰。然后监听外层表格的expand-change
事件,在事件回调中配合表格属性expand-row-keys
来控制展开的行(需求是手风琴模式,即一次最多展开一行),同时回调中去动态请求数据,数据返回后对innerList
进行赋值。
示例Demo代码如下:
<template>
<!-- 外层为用户组数据 -->
<el-table
:data="list"
style="width: 100%"
@expand-change="handleExpandChange"
:expand-row-keys="currentExpandRow"
row-key="id"
>
<el-table-column type="expand">
<!-- 内层为用户列表数组 -->
<el-table :data="innerList" style="width: 100%">
<el-table-column prop="user_id" label="用户ID" />
<el-table-column prop="nickname" label="昵称" />
</el-table>
</el-table-column>
<el-table-column prop="id" label="ID" />
<el-table-column prop="user_group_name" label="组名" />
</el-table>
</template>
对应的data
还有methods
:
<script>
export default {
data() {
return {
list: [],
innerList: [],
currentExpandRow: []
}
},
methods: {
// 获取某个用户组中的用户列表
async handleExpandChange(row) {
const currentID = this.currentExpandRow[0] ? this.currentExpandRow[0] : ''
if (currentID == row.id) {
this.currentExpandRow = []
return
}
const groupID = row.id
this.currentExpandRow = [groupID] // 控制展开行
const res = await this.axios.post('getData', {
groupID
})
this.innerList = res.data.data.data
}
}
}
</script>
一番操作后,发现展开后数据确确实实是拿到了,可是视图却不更新,确切的讲,是不会及时更新,展开后的内嵌表格会渲染上一次拿到的数据,即第一次展开无数据,第二次展开渲染第一次获取的数据,依次类推。
于是我便在事件的最后加上this.$forceUpdate()
强制更新,然而并没有什么卵用。
如何解决?
首先当然还是百度,谷歌了,可是一番查找后,并没有理想的方案,网上给的方案大多用this.$set
去处理,可实际操作起来并没有解决。
在捣鼓的过程中,发现了this.currentExpandRow
的赋值会触发视图的更新,于是我便在事件的最后用$nextTick
去赋值这个变量,结果是能成功,但是常常会出现拿不到数据(空白)。
怎么办呢?只好返回官网去找答案了。
解决
参照着官网的示例代码,我发现了好像只能在外层的list
内部去内嵌innerList
。
简单点讲,就是表格组件的更新,是看最外层的data
所绑定的变量,只要它一改变,那么视图也会相应的更新。
改动后的Demo代码如下:
<template>
<!-- 外层为用户组数据 -->
<el-table
:data="list"
style="width: 100%"
@expand-change="handleExpandChange"
:expand-row-keys="currentExpandRow"
row-key="id"
>
<el-table-column type="expand">
<template slot-scope="props">
<!-- 内层为用户列表数组 -->
<el-table :data="props.row.innerList" style="width: 100%">
<el-table-column prop="user_id" label="用户ID" />
<el-table-column prop="nickname" label="昵称" />
</el-table>
</template>
</el-table-column>
<el-table-column prop="id" label="ID" />
<el-table-column prop="user_group_name" label="组名" />
</el-table>
</template>
对应的data
还有methods
:
<script>
export default {
data() {
return {
list: [],
currentExpandRow: []
}
},
methods: {
// 获取某个用户组中的用户列表
async handleExpandChange(row) {
const currentID = this.currentExpandRow[0] ? this.currentExpandRow[0] : ''
if (currentID == row.id) {
this.currentExpandRow = []
return
}
let currentIndex = 0
this.list.some((item, index) => {
if (item.id === row.id) {
currentIndex = index
return true
}
})
const groupID = row.id
this.currentExpandRow = [groupID] // 控制展开行
const res = await this.axios.post('getData', {
groupID
})
this.$set(this.list[currentIndex], 'innerList', res.data.data.data)
}
}
}
</script>
我将原本的innerList
内嵌到list
中
DOM中是对table-column做多一层template
包裹,通过props
传每一行的innerList
作为内嵌表格的data
;
事件回调中去获取当前点击行的currentIndex
,在获取数据的最后通过$set
去做数据的赋值。
这样做就能完美的渲染内嵌表格列表了,后续还能为内嵌表格增加分页功能!
总结
接触了UI库这么久了,感觉有些需要自定义的需求写起来还是有点费脑,不知道是本人代码水平还不够高还是官方文档不够明示,还是得继续学习!
Keep learning…