需求:表格是懒加载,点击才加载子级数据,现要求修改父级或子级内容时,保留已经展开的列,且数据要更新。
<el-table
ref="deptTreeTable"
:data="list"
style="width: 100%"
row-key="id"
lazy
:load="load"
:tree-props="{
children: 'children',
hasChildren: 'hasChildren'
}"
v-loading="tableLoading"
:default-expand-all="isSearch"
v-show="showMenuList"
@expand-change="defaultExpandedKeys"
>
在data中定义
defaultExpandedKeysList: [],
treeMap: new Map(),
使用 expand-change
将点击展开、关闭的列,用 defaultExpandedKeysList 存储起来
defaultExpandedKeys(expandedRows, expanded) {
const number = this.defaultExpandedKeysList.indexOf(expandedRows)
if (expanded) {
this.defaultExpandedKeysList.push(expandedRows)
} else {
this.defaultExpandedKeysList.splice(number, 1)
}
},
定义一个展开列的方法
因为表格是懒加载,所以先自己手动执行一下load方法,在执行展开的操作
expandableListView(list) {
if (this.defaultExpandedKeysList.length > 0) {
this.defaultExpandedKeysList.forEach(element => {
// 注意: 这里必须使用表格绑定的Array中的列去展开,否则会没效果
list.forEach(deptElement => {
if (element.id === deptElement.id) {
const treeObj = this.treeMap.get(element.id)
this.load({ id: element.id }, treeObj.treeNode, treeObj.resolve)
setTimeout(() => {
this.$refs.deptTreeTable.toggleRowExpansion(deptElement, true)
})
}
})
})
}
},
在懒加载的方法里,将load的回调treeNode、resolve存起来,便于我们主动调用
load(tree, treeNode, resolve) {
if (!this.treeMap.has(tree.id)) {
this.treeMap.set(tree.id, {
treeNode,
resolve
})
}
// 调接口获取数据
getlist(params).then(res => {
const { code, data } = res
if (+code === 200) {
resolve(data)
// 调用展开方法,检测子级是否有展开列,并展开
this.expandableListView(data)
}
}).catch(() => {
resolve([]);
});
}
在表格数据接口获取之后调用展开方法
const { code, data } = res
this.list = data
// 必须使用 $nextTick
this.$nextTick(() => {
this.expandableListView(this.list)
})
今天后端反馈,接口请求频繁,点击一次查询调用很多次接口,查看代码发现,存储展开列的数组一直往里重复的添加数据,因此做一下数组去重。
方式一:手动展开列的时候先去重一遍数据
expandableListView(list) {
// 给defaultExpandedKeysList遍历去重
this.defaultExpandedKeysList = this.defaultExpandedKeysList.reduce(function(result, current) {
var exists = result.some(function(item) {
return item.submenuCode === current.submenuCode
})
if (!exists) {
result.push(current)
}
return result
}, [])
if (this.defaultExpandedKeysList.length > 0) {
this.defaultExpandedKeysList.forEach(element => {
// 注意: 这里必须使用表格绑定的Array中的列去展开,否则会没效果
list.forEach(deptElement => {
if (element.id === deptElement.id) {
const treeObj = this.treeMap.get(element.id)
this.load({ id: element.id }, treeObj.treeNode, treeObj.resolve)
setTimeout(() => {
this.$refs.deptTreeTable.toggleRowExpansion(deptElement, true)
})
}
})
})
}
},
方式二: @expand-change="defaultExpandedKeys"里,添加数据时先过滤,方式添加重复
defaultExpandedKeys(expandedRows, expanded) {
const number = this.defaultExpandedKeysList.indexOf(expandedRows)
if (expanded) { // expanded表示列的展开(true)还是关闭(false)
// 校验重复项
const exists = this.defaultExpandedKeysList.some((item) => item.submenuCode === expandedRows.submenuCode)
if (!exists) {
this.defaultExpandedKeysList.push(expandedRows)
}
} else {
this.defaultExpandedKeysList.splice(number, 1)
}
},
问题:若只存在一个子节点,删除子节点后视图不更新,后台数据显示已删除但前段表格里还存在,刷新页面之后才正常
解决:在删除接口执行成功后,手动删除此项
handleDelete(item) {
...
const { code, message } = res;
if (+code === 200) {
this.$message.success("删除成功")
this.deleteLazyTableItem(item)
} else {
this.$message.error(message);
}
...
}
// 点击删除按钮的删除方法item为行数据
deleteLazyTableItem(item) {
const store = this.$refs.deptTreeTable.store
if (item.parentId !== -1) {
// 查找父级 找到返回item 否则返回undefined
let parentRow = store.states.data.find(child => child.id === item.parentId)
if (!parentRow) {
const keys = Object.keys(store.states.lazyTreeNodeMap)
for (let i = 0; i < keys.length; i++) {
parentRow = store.states.lazyTreeNodeMap[keys[i]].find(child => child.id === item.parentId)
if (parentRow) {
break
}
}
}
parentRow.childrenCount--
const parent = store.states.lazyTreeNodeMap[item.parentId]
const index = parent.findIndex(child => child.id === item.id)
parent.splice(index, 1)
} else {
const parent = store.states.data
const index = parent.findIndex(child => child.id === item.id)
parent.splice(index, 1)
}
},