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

相关推荐
315356691318 分钟前
一文带你了解二维码扫码的全部用途
前端·后端
七月shi人26 分钟前
用claude3.7,不到1天写了一个工具小程序(11个工具6个游戏)
前端·小程序·ai编程
Billy Qin33 分钟前
Rollup详解
前端·javascript·rollup
夜寒花碎1 小时前
前端自动化测试一jest基础使用
前端·单元测试·jest
气π1 小时前
【Vue-组件】学习笔记
vue.js·笔记·学习
小徐_23331 小时前
uni-app工程实战:基于vue-i18n和i18n-ally的国际化方案
前端·微信小程序·uni-app
前端小菜鸟一枚s1 小时前
`ConstantPositionProperty` 的使用与应用
前端·javascript·cesium
JohnsonXin1 小时前
怎么使用vue3实现一个优雅的不定高虚拟列表
前端·javascript·css·html5
东望1 小时前
写代码不规范,同事两行泪 😭(工程化如何让团队协作更高效)
javascript·前端工程化
用户837701408811 小时前
前端实现个人信息脱敏(手机号、身份证号、姓名、邮箱)JavaScript代码示例
javascript