背景需求
如下图,想要在表格展开行中再嵌套一个表格,外层表格数据和内层表数据由两个接口提供,故需要用类似懒加载的功能实现。
为什么说类似懒加载,是因为我发现el-table组件自带的树形数据与懒加载并不能满足子表格组件展示字段与父表格组件展示字段不一致的需求,所以我选择采用展开行 + expand-change
事件来实现。
实现中遇到的问题
通过展开行+ expand-change
实现时,遇到一个很大的问题,就是el-table组件在更新数据内部某个属性值时,并不能实时刷新dom视图,这样会导致每次在expand-change
事件中获取到内层表格数据后,给父层数据中添加属性时视图并未刷新。
解决方法
需要在获取父层表格数据时,添加一个子层表格数据的属性值(事先声明),然后在expand-change
事件中给该属性赋值,这样el-table就能识别出数据变化并实时更新视图。
实现代码如下
注意: row-key属性是必须的,否则会导致组件无法识别当前展开行
<template>
<el-table
border
:data="allRules"
row-key="keyId"
@expand-change="expandChange"
style="width: 100%">
<el-table-column type="expand" >
<template slot-scope="props">
<el-table
:data="props.row.childrenData"
v-loading="props.row.loading"
border>
<el-table-column
prop="name"
show-overflow-tooltip
label="任务名称">
</el-table-column>
<el-table-column
prop="description"
show-overflow-tooltip
label="任务描述">
</el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column
prop="name"
show-overflow-tooltip
label="规则名称">
</el-table-column>
</el-table>
</template>
<script>
export default {
name: '',
data () {
return {
allRules: [], // 表格数据
};
},
methods: {
// 获取父层表格数据
_getAllRules (key, value) {
this.tableLoading = true;
const data = { method: 'find_rule_bases', [key]: value };
this.getAllRules({ data }).then((res) => {
if (res.code === 0) {
const result= JSON.parse(res.result);
// 获取到父层表格数据之后,遍历添加唯一id(如果有则不用加,可由后台返回)和子层表格数据
this.allRules = result.map((item, index) => {
item.keyId = index;
item.childrenData = []; // 添加子表格数据
return item;
});
}
this.tableLoading = false;
}, (err) => {
console.log(err);
this.allRules = [];
this.tableLoading = false;
});
},
// 获取子层表格数据并更新allRules数据
expandChange (row, expandedRows) {
if (!row.children) {
// 通过$set属性可设置loading实现实时加载loading效果(经过测试,通过$set直接给父层数据声明子层数据时会出现报错,所以才在获取父层表格数据时声明子层表格数据)
this.$set(row, 'loading', true);
const data = {
'method': 'find_job_schedules',
'rule_id': row['rule_id']
};
this.getDispatchTask({ data }).then((res) => {
if (res.code === 0) {
const taskData = JSON.parse(res.result);
// 遍历父层表格数据
this.allRules.forEach((temp, index) => {
// 找到当前展开的行,把获取到的数据赋值进去
if (temp.keyId === row.keyId) {
this.allRules[index].childrenData = taskData || [];
}
});
}
this.$set(row, 'loading', false);
}, (err) => {
this.$set(row, 'loading', false);
});
}
}
}
}