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

相关推荐
Hello.Reader15 分钟前
Flink 文件系统通用配置默认文件系统与连接数限制实战
vue.js·flink·npm
wuhen_n17 分钟前
JavaScript内置数据结构
开发语言·前端·javascript·数据结构
大鱼前端18 分钟前
为什么我说CSS-in-JS是前端“最佳”的糟粕设计?
前端
不爱吃糖的程序媛21 分钟前
Capacitor:跨平台Web原生应用开发利器,现已全面适配鸿蒙
前端·华为·harmonyos
AC赳赳老秦23 分钟前
2026国产算力新周期:DeepSeek实战适配英伟达H200,引领大模型训练效率跃升
大数据·前端·人工智能·算法·tidb·memcache·deepseek
CHU72903524 分钟前
淘宝扭蛋机抽盒小程序前端功能解析:解锁趣味抽盒新体验
前端·小程序
-凌凌漆-34 分钟前
【npm】npm的-D选项介绍
前端·npm·node.js
鹿心肺语1 小时前
前端HTML转PDF的两种主流方案深度解析
前端·javascript
海石1 小时前
去到比北方更北的地方—2025年终总结
前端·ai编程·年终总结
一个懒人懒人1 小时前
Promise async/await与fetch的概念
前端·javascript·html