vue 使用 element-plus 中的el-tree 卡顿问题

使用 Element Plus UI 框架中的 el-tree 组件的示例。el-tree 是一个树形控件,通常用于展示具有层级关系的数据。下面是对代码中关键部分的介绍:

:树形控件的根元素,用于定义树的基本属性和事件。

class=“video-tree”:为树控件添加了一个 CSS 类,可能用于定制样式。

ref=“eltree”:为树控件注册了一个引用名称 eltree,这样可以通过 this.$refs.eltree 在 Vue 实例中访问树的实例方法和数据。

:data=“treeData”:绑定了树的数据源 treeData,这是一个包含树节点的数组。

:props=“{ children: ‘children’, label: ‘label’, hasChildren: ‘hasChildren’ }”:定义了树节点对象的属性配置,指定了子节点、标签和是否有子节点的字段名。

:lazy=“true”:启用了懒加载功能,意味着树节点的子节点将按需加载而不是一次性加载所有节点。

:load=“loadNode”:定义了懒加载时用于加载子节点的函数 loadNode。

@node-click=“handleNodeClick”:为树节点点击事件绑定了处理函数 handleNodeClick。

@node-contextmenu=“handleNodeMenuClick”:为树节点右键菜单事件绑定了处理函数 handleNodeMenuClick。

:accordion=“false”:设置手风琴效果为 false,意味着不会在点击节点时自动折叠其他同级节点。

:highlight-current=“true”:高亮当前选中的节点。

node-key=“id”:指定了树节点的唯一标识字段为 id。

<template #default=“{ node, data }”>:使用作用域插槽自定义树节点的内容,其中 { node, data } 是插槽的参数,包含了当前节点的信息。

:在每个树节点上使用 el-dropdown 组件来创建一个下拉菜单,触发方式为右键点击(trigger=“contextmenu”)。

:ref="‘dropdown’+ node.data.id ":为每个下拉菜单实例注册引用,引用名称与节点的 id 相关联。

@visible-change=“(visible) => handleVisibleChange(node, visible)”:为下拉菜单的可见性变化事件绑定处理函数 handleVisibleChange。

<template #dropdown>:使用作用域插槽自定义下拉菜单的内容,条件是当前节点等于 currentDrop。

和 :定义下拉菜单的菜单项,包括“新建”、“删除”、“重命名”和“属性”等操作。

@click=“handleModal”、@click=“deleteNodes”、@click=“renameNode” 和 @click=“handleMessageModal”:分别为下拉菜单项绑定了点击事件处理函数。

这段代码展示了如何在 Element Plus 的 el-tree 组件中集成懒加载、自定义节点内容、下拉菜单以及事件处理

<el-tree
                    class="video-tree"
                    ref="eltree"
                    :data="treeData" 
                    :props="{ 
                      children: 'children',
                      label: 'label',
                      hasChildren: 'hasChildren' 
                    }"
                    :lazy="true"
                    :load="loadNode"
                    @node-click="handleNodeClick"
                    @node-contextmenu="handleNodeMenuClick"
                    :accordion="false"
                    :highlight-current="true"
                    node-key="id"
                    
                    >
                    <template #default="{ node, data }"> 
                      <el-dropdown  
                      trigger="contextmenu" 
                      :ref="'dropdown'+ node.data.id "
                      @visible-change="(visible) => handleVisibleChange(node, visible)"
                      >

                        <span class="el-dropdown-link">
                          {{ node.label }}
                        </span>
                      <template 
                      #dropdown
                      v-if="currentDrop && currentDrop == node.data.id"
                      >
                        <el-dropdown-menu>
                          <el-dropdown-item 
                          :disabled="isNewProject"
                          @click="handleModal"
                          >
                            新建
                          </el-dropdown-item>
                          <el-dropdown-item 
                          :disabled="!nodeIdFlag"
                          @click="deleteNodes"
                          >
                            删除
                          </el-dropdown-item>
                          <el-dropdown-item 
                          @click="renameNode"
                          :disabled="!displayNameFlag"
                          >
                            重命名
                          </el-dropdown-item> 
                          <el-dropdown-item 
                          :disabled="!descriptionFlag"
                          @click="handleMessageModal"
                          >
                            属性
                          </el-dropdown-item> 
                        </el-dropdown-menu>
                      </template>
                    </el-dropdown>
                    </template>
            </el-tree>

函数签名:

loadNode(node, resolve):这是懒加载函数的标准形式,接收两个参数,node 是当前需要加载子节点的树节点,resolve 是一个回调函数,用于将加载的子节点数据“解决”并填充到树节点中。
检查节点属性:

let flag = node.data?.isAbstract:尝试从当前节点的数据中获取 isAbstract 属性,用于判断节点是否是抽象的。
条件判断:

if (node.level >= 2 && !flag):如果节点的层级大于或等于2且不是抽象节点,则执行内部的代码块。
定义变量:

let nodeClassToReturn = ‘Object’:定义一个变量 nodeClassToReturn 并赋值为 ‘Object’,这可能是用来指定要返回的节点类型。
发起 API 请求:

let api = new ModellingServiceApi();:实例化一个 API 服务类 ModellingServiceApi。
let res = api.browseNode(…):调用 browseNode 方法发起 API 请求,请求参数包括会话 ID (sid)、节点 ID (nodeid)、返回的节点类型 (nodeClassToReturn) 等。
处理响应数据:

let arr = JSON.parse(JSON.stringify(res)):将 API 响应结果转换成数组形式。
arr.map(…):遍历数组,对每个节点对象进行处理,如设置 id 和 label。
过滤和设置子节点:

let tempArr = arr.filter(…):过滤数组,排除那些浏览名称以 “#” 开头的节点。
node.children = tempArr:将过滤后的数组赋值给当前节点的 children 属性,表示子节点列表。
使用 resolve 回调:

return resolve(res):调用 resolve 回调函数并传入子节点数据,完成懒加载过程。
错误处理:

catch(err){ resolve([]) }:如果请求失败或发生错误,调用 resolve 并传入空数组,表示没有子节点。
其他逻辑分支:

if(!flag){ … } else { … }:根据 flag 的值调用不同的函数来加载子节点数据。
方法调用:

this.getChildrenTreelist(node, resolve) 和 this.loadSubChildrenTree(node, resolve):可能是定义在 Vue 组件中的其他方法,用于根据不同的条件加载子节点数据。

loadNode(node,resolve){
        let flag = node.data?.isAbstract

        if (node.level >= 2 && !flag) {
          let nodeClassToReturn ='Object' 
        let nodeid = node.data.nodeId
        try{
            console.time()
            let api = new ModellingServiceApi();
            let res =   api.browseNode({sid:SID,
                            nodeId:nodeid,
                            nodeClassToReturn:[nodeClassToReturn],
                            isForward:true,
                            limit:999,
                            page:0}); 

            console.timeEnd()

            let arr =[] 
            arr = JSON.parse(JSON.stringify(res))
            arr.map((item)=>{
              item.id = item.nodeId
              let label =item.name? splitLastHyphen(item.name,'-'):""
              item.label =label[0]
              this.hasChildList.map((idx)=>{
                 item.data = idx
              })
            }) 
            let tempArr = arr.filter((item)=>{return item.browseName.charAt(0) !== "#"})
            node.children = tempArr
          return  resolve(res)
          // return resolve(data);
        } 
        catch(err){
          resolve([])
        }
      }
        if(!flag){
            this.getChildrenTreelist(node,resolve)
        }else{
          this.loadSubChildrenTree(node,resolve)
        }
      },

注意事项:在loadNode() 方法中不要轻易使用 async await 会造成UI绘制异常卡顿

在 loadNode() 方法中使用 async/await 与避免使用它取决于具体的应用场景和性能考虑。async/await 是 JavaScript 中处理异步操作的一种非常直观和方便的方式,它建立在 Promise 之上,使得异步代码的写法看起来更像是同步的。然而,在某些情况下,尤其是在性能敏感的环境下,比如懒加载大量数据时,不使用 async/await 可能更合适。以下是一些考虑点:

避免额外的微任务调度:
async/await 在内部可能会创建额外的微任务,这可能会稍微增加调度的开销。在懒加载树节点时,如果对性能要求极高,可能需要避免这种开销。

减少 Promise 解决的复杂性:
使用 async/await 时,每个 await 表达式都会创建一个新的 Promise。在处理大量数据时,这可能会导致额外的内存使用和垃圾回收压力。

保持回调的简洁性:
当使用 async/await 时,错误处理通常使用 try…catch 语句。如果 loadNode() 方法已经非常复杂,添加额外的错误处理可能会增加代码的复杂性。

避免阻塞异步执行队列:
在某些情况下,如果 loadNode() 方法中包含多个 await 调用,它们会按顺序执行,这可能会阻塞异步执行队列,延迟其他异步操作的执行。

使用传统的 Promise 链:
不使用 async/await 的话,可以继续使用 Promise 链式调用(thenable chains),这种方式在处理大量异步操作时可能更加灵活和高效。

保持代码的一致性:
如果你的项目或团队倾向于使用传统的 Promise 风格,那么在 loadNode() 方法中保持一致性可能更有利于代码的可维护性。

避免在事件循环中的不必要等待:
await 会在等待 Promise 解决时暂停函数的执行,这在某些情况下可能会导致不必要的等待,尤其是在主线程上,这可能会影响 UI 的响应性。

使用同步代码的错觉:
async/await 让异步代码看起来像同步代码,这可能会误导开发者忽视异步操作的真正性质,从而在性能优化时忽视了异步操作的开销。

考虑错误处理的开销:
使用 async/await 时,错误处理需要使用 try…catch,这可能会在编译时引入额外的开销,尤其是在处理大量数据时。

避免在 Web Workers 中使用:
如果你打算将 loadNode() 方法中的逻辑放在 Web Worker 中执行,使用 async/await 可能不太合适,因为 Web Workers 环境中不支持 async/await。

总之,是否在 loadNode() 方法中使用 async/await 应根据具体情况和性能要求来决定。如果性能是关键考虑因素,并且你正在处理大量数据,可能需要考虑使用传统的 Promise 或其他异步模式来避免潜在的性能问题。

以上就是文章全部内容了,如果喜欢这篇文章的话,还希望三连支持一下,感谢!

element-plus 是一个基于 Vue.js 的 UI 组件库,el-tree-select 是其的一个组件,用于实现树形结构的下拉选择。 el-tree-select 组件是在 el-select 组件的基础上进行扩展,使其支持树形结构的数据。使用 el-tree-select,我们可以在下拉列表展示树状数据,并支持选择树节点的功能。 el-tree-select 的使用方式大致分为以下几步: 1. 引入 element-plus 库,确保已安装并正确引入相关 CSS 和 JS 文件。 2. 在组件使用 el-tree-select 标签,通过 v-model 绑定选的节点,将选的节点值赋给 data 的一个变量。 3. 设置 el-tree-select 的配置项,包括数据源、显示字段、样式等。 4. 响应选择事件,在 el-tree-select 标签上绑定 change 事件,根据选的节点进行相应操作。 配置项常用的属性有: - data:树形数据源,可以是一个数组或者通过异步加载数据。 - label-prop:用于显示节点文本的属性名。 - value-prop:用于取值的属性名。 - default-expand-all:是否默认展开全部节点。 - filterable:是否支持输入框搜索el-tree-select 还提供了其他的配置项和方法,可以根据具体需求进行调整和使用。 总之,element-plus 的 el-tree-select 组件提供了一种简单易用的方式来展示和选择树形数据,在Vue.js项目非常实用。通过合理配置,我们可以灵活定制树形下拉选择框的功能和样式,使其符合项目的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小纯洁w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值