在开发过程中需要在表格展开行中再嵌套一个表格,当element自带的组件满足不了(外层表格数据和内层表数据由两个接口提供),需要用类似懒加载的功能实现,所以选择采用展开行 + expand-change事件来实现。
实现中遇到的问题
通过展开行+ expand-change实现时,遇到一个很大的问题,就是el-table组件在更新数据内部某个属性值时,并不能实时刷新dom视图,这样会导致每次在expand-change事件中获取到内层表格数据后,给父层数据中添加属性时视图并未刷新。
解决方法
需要在获取父层表格数据时,添加一个子层表格数据的属性值(事先声明),然后在expand-change事件中给该属性赋值,这样el-table就能识别出数据变化并实时更新视图。
实现代码如下
注意: row-key属性是必须的,否则会导致组件无法识别当前展开行
<template>
<el-table
border
:data="tableData"
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 {
tableData: [], // 表格数据
};
},
methods: {
// 获取父层表格数据
_getAllRules (key, value) {
let parmas= { method: 'find_rule_bases', [key]: value };
API_Rules.getAllRules(parmas).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;
});
}
}, (err) => {
console.log(err);
this.tableData= [];
});
},
// 获取子层表格数据并更新tableData数据
expandChange (row) {
if (!row.childrenData ) {
// 通过$set属性可设置loading实现实时加载loading效果(经过测试,通过$set直接给父层数据声明子层数据时会出现报错,所以才在获取父层表格数据时声明子层表格数据)
this.$set(row, 'loading', true);
let params = { };
API_Rules.getchildren( params ).then((res) => {
if (res.code === 0) {
const children= JSON.parse(res.result);
// 遍历父层表格数据
this.allRules.forEach((temp, index) => {
// 找到当前展开的行,把获取到的数据赋值进去
if (temp.keyId === row.keyId) {
this.allRules[index].childrenData = children || [];
}
});
}
this.$set(row, 'loading', false);
}, (err) => {
this.$set(row, 'loading', false);
});
}
}
}
}