前言
在我们实际开发中,由于后端返回的节点数据量庞大,而用户往往没有要看到所有数据的需求,如果在页面加载中,将页面的所有节点数据都加载出来,无疑是浪费用户宝贵的时间,因此,就有了节点的懒加载的需求,用户想展开哪个节点,我们就给他展示什么数据(异步的从后台发送请求获取当前节点数据然后进行渲染)。
一、如何实现懒加载
element ul el-tree异步加载方式
<el-tree
:props="props"
:load="loadNode"
lazy
show-checkbox>
</el-tree>
<script>
export default {
data() {
return {
props: {
label: 'name',
children: 'zones',
isLeaf: 'leaf'
},
};
},
methods: {
loadNode(node, resolve) {
if (node.level === 0) {
return resolve([{ name: 'region' }]);
}
if (node.level > 1) return resolve([]);
setTimeout(() => {
const data = [{
name: 'leaf',
leaf: true
}, {
name: 'zone'
}];
resolve(data);
}, 500);
}
}
};
</script>
在官方文档中,我们可以知道el-tree要实现异步加载节点需要用到load、lazy属性。
- loda: 加载子树数据的方法,仅当 lazy 属性为true 时生效。
- lazy: 是否懒加载子节点,需与 load 方法结合使用。
在methods中,loadNode方法给我们返回了两个参数:
- node:返回当前节点的数据
- resolve: 渲染节点数(用来获取到节点数据后渲染使用的)
下面直接上示例代码
<el-tree
ref="tree"
:props="props"
:load="loadNode"
node-key="id"
// node-key 为所有节点之前的唯一标识
:default-expanded-keys="nodeIdArr"
// nodeIdArr为异步加载时默认展开是的节点arr,从第一个根节点到最后展开节点的id,例如[1, 2, 12]
lazy
:highlight-current="true"
// 点击高亮
@node-click="handleNodeClick"
// 点击事件,每次点击节点是都会触发,放回当前节点的node
>
</el-tree>
export default {
data() {
return {
props: {
label: 'nodeName',// 节点渲染时的显示的名字
children: 'zones', // 节点是否拥有子节点
isLeaf: 'leaf', // 判断显示节点icon
},
resData: [],
nodeIdArr: [],
showNodeId: Number,
nodeId: Number,
};
},
mounted() {
this.init();
},
methods: {
async init() {
await this.getUserLocation();
},
// 点击选取事件
handleNodeClick(data, node) {
console.log('data', data, node);
this.nodeId = node.data.id;
},
// 异步树叶子节点懒加载逻辑
async loadNode(node, resolve) {
// 一级节点处理
if (node.level === 0) {
await this.requestTree(resolve);
}
// 其余节点处理
if (node.level >= 1) {
this.getIndex(node, resolve);
}
},
// 异步加载叶子节点数据函数
async getIndex(node, resolve) {
const nodeId = node.data.id;
await this.requestData(nodeId);
resolve(this.resData);
},
// 首次加载一级节点数据函数
async requestTree(resolve) {
await this.requestData(0);
resolve(this.resData);
},
// 获取该节点下的字节点
async requestData(val) {
const res = await this.$api.org.node.allChildNodeByParent(val, { dismissLoading: true });
const resDatas = res.data.data;
_.forEach(resDatas, item => {
// 赋值节点数据,用于显示节点icon
if (item.childCount === 0) {
item.leaf = true; // 不为叶子节点
} else {
item.leaf = false; // 为叶子节点
}
});
this.resData = resDatas;
if (val === this.showNodeId) {
// 这一步为了懒加载中等节点渲染完毕后点击到我们需要的节点上去
this.$refs.tree.setCurrentKey(this.showNodeId);
}
},
// 获取到本帐号所对应位置的nodeId数组
async getUserLocation() {
const res = await this.$api.org.node.getUserLocation({ dismissLoading: true });
if (res.data.code === 0) {
this.nodeIdArr = res.data.data;
// showNodeId 为了后期节点渲染成功后点击到需要的节点上做准备
this.showNodeId = res.data.data[res.data.data.length - 1];
} else {
this.$message({
message: res.data.msg,
type: 'error',
});
}
},
},
};
</script>