需求
需要在树形控件中逐级显示公司、部门以及不同部门下的项目信息。其中,公司及部门信息的结构是一致的,但是项目是另一种结构(类)。所以,树结构中需要用到两种不同结构的数据。
El-tree
主要属性
下面是一个el-tree控件,包含了其中主要的属性
html
<el-tree
:data="projectOptions" //树形图所绑定的数据
:props="defaultTreeProps" //配置选项,共四项,见下文
:expand-on-click-node="false"
:filter-node-method="filterNode"
:default-expanded-keys="defaultShowNodes" //树形控件展开节点,是一个数组,从根节点到叶子节点
:current-node-key="currentNodeKey"
:load="loadTreeNode" //lazy模式下,点击节点前的小三角时触发,加载该节点数据数据
ref="tree"
lazy //懒加载,即点击节点前的小三角时才开始加载(获取)数据
:highlight-current="true"
@node-click="handleNodeClick" //点击节点所要处理的业务逻辑
style="max-height:calc(100vh - 180px); overflow:auto;"
/>
配置选项props
javascript
defaultTreeProps: {
children: 'children',
label: 'deptName',
isLeaf: 'leaf'
},
Label
节点标签,即每个节点所显示的字符,可以直接指定一个字符串,表示节点对象的某个属性值,比如上面例子中'deptName'表示结果数据中的deptName字段(部门名称)作为树形控件的label。
但是,因为我的树形图最后的叶子节点是项目,里面是没有deptName字段的,我希望叶子节点显示项目名称,所以,我就需要用一个方法来动态控制label的值:在前面的节点使用deptName,最后的叶子节点使用projectName,如下,我是通过返回的数据中是否有deptName这个字段来判断的:
javascript
label: function(data,node){
if(data.deptName) return data.deptName
else return data.projectName;
},
isLeaf
lazy模式下,用于指定节点是否为叶子节点。
lazy模式下,在点击节点时才进行该层数据的获取,默认情况下 Tree 无法预知某个节点是否为叶子节点,所以会为每个节点添加一个下拉按钮,如果节点没有下层数据,则点击后下拉按钮会消失。但是,如果你获取数据时就知道这个节点是否是叶子节点,也可以提前告知 Tree ,从而避免在叶子节点前渲染不必要的下拉按钮。比如最开始的示例中,isLeaf: 'leaf'表示使用节点对象中的leaf属性来告知Tree是否是叶子节点(在部门实体类中有这么个数据项)。
但是,我要在最后一级部门节点下要加载项目信息,所以,不可以用部门对象中的leaf属性,这会导致在最后一级部门节点处没有小三角,无法点击,也就无法触发该节点的:load方法来加载项目数据。所以,我同样需要动态判定是否是leaf:这里我检查,如果数据中有projectName这个字段,也就是项目信息,它就是叶子节点,否则,非叶子节点。这里根据实际业务来选择判定方法。
javascript
isLeaf: function(data){
if(data.projectName) return true;
else return false;
}
小结
综上,prop中的选项,即可以直接指定使用节点对象中的某个属性来赋值,也可以使用一个函数来动态计算。函数中有data和node两个默认入参(具体可参考官网中el-tree页面关于prop的表格:Element - The world's most popular Vue UI framework)。
(初始化)数据加载 on load
根据实际业务需求,逐层加载数据,比如下面的代码,第一层加载公司信息,第二层和第三层分别加载部门数据,最后一层加载项目数据。
javascript
async loadTreeNode(node, resolve) {
if (node.level === 0) {
await this.getTreeRoot(node, resolve);
}else if(node.level === 1 || node.level === 2){
await this.getDeptList(node, resolve);
}else{
await this.getProjectList(node, resolve);
}
},
下面是获取部门信息的示例,将返回值中的数据信息提取出来,赋给resolve返回。
javascript
getDeptList(node, resolve) {
listDept({parentId: node.data.deptId}).then(res => {
const {data} = res; //提取res中的data部分
resolve(data);
});
}
},
在JavaScript中,
resolve
是一个Promise对象的方法,用于返回一个已解析(resolved)的Promise对象。Promise是一种用于处理异步操作的对象,它可以将异步操作封装为一个Promise对象,然后通过
resolve
方法将Promise对象状态设置为已解析(resolved),表示异步操作已成功完成。
resolve
方法接受一个参数,该参数可以是任意类型的值,通常是一个表示异步操作的结果。当调用resolve
方法时,Promise对象的状态将从pending
变为fulfilled
,然后通过.then
方法执行与该Promise对象相关的成功回调函数。需要注意的是,Promise对象的状态一旦被解析或拒绝(rejected)后,就不能再次改变。所以,在调用
resolve
方法后,Promise对象的状态将保持为已解析状态,而不能再变为未解析状态。
响应节点点击事件on node-click
这里可以定义当鼠标点击树形图中的某个节点时需要给出什么响应,共有三个参数:传递给 data
属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身。