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

相关推荐
柏箱3 分钟前
PHP基本语法总结
开发语言·前端·html·php
新缸中之脑13 分钟前
Llama 3.2 安卓手机安装教程
前端·人工智能·算法
hmz85617 分钟前
最新网课搜题答案查询小程序源码/题库多接口微信小程序源码+自带流量主
前端·微信小程序·小程序
看到请催我学习23 分钟前
内存缓存和硬盘缓存
开发语言·前端·javascript·vue.js·缓存·ecmascript
blaizeer1 小时前
深入理解 CSS 浮动(Float):详尽指南
前端·css
速盾cdn1 小时前
速盾:网页游戏部署高防服务器有什么优势?
服务器·前端·web安全
小白求学12 小时前
CSS浮动
前端·css·css3
什么鬼昵称2 小时前
Pikachu-csrf-CSRF(POST)
前端·csrf
XiaoYu20022 小时前
22.JS高级-ES6之Symbol类型与Set、Map数据结构
前端·javascript·代码规范
golitter.2 小时前
Vue组件库Element-ui
前端·vue.js·ui