element-ui el-tree大数据量取消勾选卡顿问题

前言

Element-UIel-tree 组件是一个非常常用的组件,它可以用来显示和处理树形结构数据。然而,当处理大数据量时,重置为未勾选状态的操作可能会导致页面卡顿,这是因为该操作要进行大量的循环,而这些循环有些是不需要的。

分析与解决方法

el-tree选中和取消勾选,会执行node.js文件下的setChecked函数。在setChecked函数内会递归节点,设置勾选状态。

Element-UI el-tree 源码文件路径:packeages\tree\src\model\node.js

函数执行逻辑如下:

graph TB Q(setChecked) --> P(调用 getChildState 设置节点状态) --> O{handleDescendants} --> A{depp} A{depp}-->|true| B(进入 for 循环递归) -.-> Q -.-> P -.-> F(reInitChecked 递归设置父级状态) -.-> P A{depp}-->|false| I(reInitChecked 递归设置父级状态)

知道了大概的逻辑,就可以打断点或者加console.log来分析代码。为了能更好的在文章中展示,本次使用console.log来分析代码。

使用三种不同的方法测试,重置勾选状态,包括在5000+数据的情况下需要耗时多久。

  1. 使用官方推荐的this.$refs.tree.setCheckedKeys([])方法,设置所有选中节点为未勾选状态;
js 复制代码
let nodes = this.$refs.tree.getCheckedNodes()  
nodes.map(item => { 
    this.$refs.tree.setChecked(item)  
})

一次性重置5000+条数据耗时:

  1. 使用getCheckedNodes()获取选中节点,然后再使用setChecked循环设置未勾选状态;

一次性重置5000+条数据耗时:

  1. 使用setChecked,只设置选中节点的父级为未勾选状态;
js 复制代码
this.$refs.tree.setChecked('4', false, true)

一次性重置5000+条数据耗时:

总结:

  • 测试1.全部节点循环了一遍,其中包括未勾选的节点;
  • 测试2.勾选了5个节点。取消勾选状态,循环调用getChildState函数9次,加上循环调用this.$refs.tree.setChecked的次数,总共循环了14次;
  • 测试3.只循环调用getChildState函数3次;

以上,只计算了getChildState函数调用次数,getChildState函数内还有for循环,如果在大数据量的情况下,这么多次的循环和递归必然会造成卡顿。

尽量使用测试3.的方法,只针对父级设置为未勾选状态

源码

html 复制代码
<template>
  <div>
    <button @click="reset">重置</button>
    <el-tree
        ref="tree"
        :data="data"
        @check="check"
        show-checkbox
        node-key="id"
        :default-expanded-keys="[]"
        :props="defaultProps">
    </el-tree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      data: [{
        id: 1,
        label: '一级 1',
        children: [{
          id: 4,
          label: '二级 1-1',
          children: [{
            id: 9,
            label: '三级 1-1-1'
          }, {
            id: 10,
            label: '三级 1-1-2'
          }]
        }, {
          id: 99,
          label: 'asasa'
        },
          {
            id: 88,
            label: 'vcvcvc'
          }]
      }, {
        id: 2,
        label: '一级 2',
        children: [{
          id: 5,
          label: '二级 2-1'
        }, {
          id: 6,
          label: '二级 2-2'
        }]
      }, {
        id: 3,
        label: '一级 3',
        children: [{
          id: 7,
          label: '二级 3-1'
        }, {
          id: 8,
          label: '二级 3-2'
        }]
      }],
      defaultProps: {
        children: 'children',
        label: 'label'
      },
      setData: new Set()
    };
  },
  created() {
    for (let i = 0; i < 5000; i++) {
      this.data[0].children.push({
        id: i + 100,
        label: i
      })
    }
  },
  methods: {
    reset() {
      console.time('耗时')
      // this.$refs.tree.setCheckedKeys([])

      let arr = Array.from(this.setData)
      let node = null
      for (let item of arr) {
        node = this.$refs.tree.getNode(item)
        if (!node.checked && !node.indeterminate) continue
        this.$refs.tree.setChecked(item, false, true)
      }

      let nodes = this.$refs.tree.getCheckedNodes()
      console.log(nodes)
      // nodes.map(item => {
      //   this.$refs.tree.setChecked(item)
      // })

      console.timeEnd('耗时')
    },
    check(a) {
      let node = this.$refs.tree.getNode(a.id)
      this.setData.add(node.parent.key || node.key)
    }
  }
};
</script>

建议

Vue2项目,建议大数据量的树形结构数据,使用vue-easy-tree库,vue-easy-tree很好的实现了虚拟列表树。

vue-easy-tree使用el-tree二次开发,所以可以很好的支持el-tree的 API,可以很方便的替换原有的el-tree

相关推荐
掘金者阿豪2 分钟前
把业务数据变成共享仪表盘:Metabase可视化与远程访问实践
前端·后端
kyriewen22 分钟前
折腾了半年 AI 编程工作流,最后发现效率瓶颈是桌上那块屏幕
前端·javascript·ai编程
蜗牛前端1 小时前
codex 全流程开发上线的高颜值礼簿小程序
前端·微信小程序
大龄秃头程序员1 小时前
我在图文流 App 里落地双层缓存、弱网降级与 OOM 治理
前端
老王以为2 小时前
React Renderer 分离的多平台架构
前端·react native·react.js
hunterandroid2 小时前
Kotlin Coroutines 与 Flow:让异步任务更清晰
前端
Bigger2 小时前
从零搭建 AI 代码审查服务:一份前端也能看懂的 Python 学习笔记
前端·ci/cd·ai编程
lichenyang4532 小时前
JSAPI、NAPI、Biz、Imp:ASCF Demo 如何真正调用系统能力和 C++ 能力
前端
lichenyang4533 小时前
IPC、JSVM、UIThread、libuv:ASCF 架构图里最容易混的几个词
前端
用户059540174463 小时前
Redis记忆存储故障恢复测试踩坑实录:手动测试让我漏掉了2个一致性Bug
前端·css