vue2:树形控件el-tree中加载两种不同结构的数据

需求

需要在树形控件中逐级显示公司、部门以及不同部门下的项目信息。其中,公司及部门信息的结构是一致的,但是项目是另一种结构(类)。所以,树结构中需要用到两种不同结构的数据。

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、节点组件本身。

相关推荐
活宝小娜24 分钟前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点27 分钟前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow28 分钟前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o29 分钟前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
刚刚好ā1 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
yqcoder3 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
会发光的猪。4 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客4 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
周全全4 小时前
Spring Boot + Vue 基于 RSA 的用户身份认证加密机制实现
java·vue.js·spring boot·安全·php
Domain-zhuo5 小时前
什么是JavaScript原型链?
开发语言·前端·javascript·jvm·ecmascript·原型模式