需求场景
一棵树的业务数据有几万条,所以用懒加载比较合适。但是要想定位某个叶子节点,就必须要通过后端接口进行过滤数据,并在前端展示过滤后的树结构。而且过滤后的树结构中的叶子节点还可以进行懒加载
实现
思路:el-tree 懒加载第一层级时,根据接口返回的数据,渲染过滤后的树
难点:由于 el-tree 的每次懒加载只能显示一个层级的节点,如果接口返回的数据是多层级的树,那么更深层级的节点就没有渲染出来
解决方案:不用 el-tree 默认的懒加载方式,自己来实现懒加载。查看 el-tree 文档,其中updateKeyChildren方法 和 node-expand事件可以满足需求
1.el-tree 配置如下
<el-tree
ref="tree"
v-loading="loading"
node-key="id"
default-expand-all
:data="treeData"
:props="defaultProps"
:render-content="renderContent"
@node-expand="nodeExpand"
/>
- 使用
render-content指定渲染函数
renderContent(h, { node, data, store }) {
// 如果是叶子节点,就让展开/收缩按钮显示
if (node.childNodes.length === 0) {
node.isLeaf = false
node.expanded = false
} else {
// 如果节点已经展开,并且存在子节点,则loaded设为true
// 表示已加载过了,下次展开时,就不要请求数据了
if (node.expanded) node.loaded = true
}
return (
<span class="custom-tree-node">
<span>{node.label}</span>
</span>);
},
- node-expand 事件:
nodeExpand(data, node, vueComponent) {
// 设置图标为收缩图标,等加载数据后再展开,达到与el-tree默认懒加载同样的效果
node.expanded = false
if (!node.loaded) { // 当没有加载过的节点才会请求数据
node.loading = true
this.fetchTreeData({type: 'load', id: data.id}).then(res => {
node.loaded = true
node.loading = false
node.expanded = true
if (res && res.length) {
// 更新当前节点的子节点
this.$refs.tree.updateKeyChildren(data.id, res)
} else {
node.isLeaf = true
}
})
} else {
node.expanded = true
}
},
- 最终效果: