tree 的节点懒加载

  1. 在实际项目开发中,当 tree 的某个节点大于 2000 个时,dom 渲染起来就非常慢,整个页面就会卡了起来.
  2. 基于 vue elementUI 来开发,用到了 InfiniteScroll 无限滚动 Tree 树形控件
  3. 来个 demo,具体看下 tree 子节点过多时的卡顿吧。
  1. 优化思路就是 前端刚开始只加载 10 个子节点,当滚动到底部时,再增加 10 个。
<div id="app">
  <div
    class="tree-box1"
    :infinite-scroll-immediate="false"
    v-infinite-scroll="load"
  >
    <el-tree
      :data="curList"
      v-loading="loading"
      default-expand-all
      :props="defaultProps"
      @node-click="handleNodeClick"
    ></el-tree>
  </div>
</div>
<style>
  .tree-box1 {
    height: 200px;
    overflow: auto;
  }
</style>

<script>
  var Main = {
    data() {
      return {
        loading: false,
        curtreePageSize: 10,
        allList: [],
        curList: [],
        defaultProps: {
          children: 'children',
          label: 'label',
        },
      }
    },
    methods: {
      //滚动轴滚动最底部触发,tree的数组动态增加
      load() {
        if (this.allList.length) {
          console.log('滚动')
          this.curtreePageSize += 10
          this.curList = this.sliceTree(this.allList, this.curtreePageSize)
        }
      },
      handleNodeClick(data) {
        console.log(data)
      },
      //tree数组的截取,默认截取10个,可以动态配置
      sliceTree(data, len = 10) {
        return [
          {
            label: '一级 1',
            children: data.slice(0, len),
          },
        ]
      },
      // 这是模拟跟后端的请求;用setTimeout模拟
      impersonationRequest() {
        this.loading = true
        let arr = []
        for (let i = 1; i < 4000; i++) {
          arr.push({ label: `二级 1-${i}` })
        }
        setTimeout(() => {
          this.allList = arr
          this.curList = this.sliceTree(this.allList)
          this.loading = false
        }, 1000)
      },
    },
    mounted() {
      this.impersonationRequest()
    },
  }
  var Ctor = Vue.extend(Main)
  new Ctor().$mount('#app')
</script>
  1. 好了基本完结,假如你不用el-tree自带的关键字过滤树节点的话。
    又或者后端大佬愿意帮你写个接口,返回过滤后的tree给你;
    不然的话,你就自己来实现了。el-tree本身的过滤是没有问题的,但是你用了懒加载,例如只加载了10个,它只会在你10个里面来进行搜索;你就需要自己写个算法来实现;
    核心代码如下
/**
 * data 为 tree数据
 * name 为 筛选关键词
 **/
const filterTree  = (data, name) => {
           // 当name数据为空时,返回默认的10个数据dom
           if (!name) {
               this.curList = this.sliceTree(this.allList)
               return
           }
           const PrimaryNode = [...data] //数组
           // 递归的方法,来判断
           function traverse (node) {
               node.forEach(v => {
                   //假如当前节点的属性满足 关键词,则将当前节点的visible属性设置为tree
                   v.visible = v.label.includes(name)
                   //如果纯在子节点,就递归调用本函数
                   if (v.children) {
                       traverse(v.children)
                   }
                   /* 当前节点visible为false, 且有子节点的再判断一次
                    假如子节点存在visible为true,则父节点的visible也设置成tree
                    这个涉及到递归的执行顺序问题,我们假如搜索的孙子节点三级,
                    const tree = [{
                       label:'一级',
                       children:[{
                           label: '二级',
                           children:[{
                           label: '三级',
                           }]
                       }]
                   }]
                   下面代码执行顺序是从最深处开始执行,然后渐渐到外层的,所以不会有问题;
                   */
                   if (!v.visible && v.children) {
                       v.visible = v.children.some(child => child.visible)
                   }
               })
           }
           //第二个函数的作用,就是过滤掉visible为false的选项。比较容易理解
           function filterName (node) {
               const newNode = node.filter(v => v.visible)
               newNode.forEach(v => {
                   if (v.children) {
                       v.children = filterName(v.children)
                   }
               })
               return newNode
           }
           traverse(PrimaryNode)
           const filterNode = filterName(PrimaryNode).slice(0,100)
           if(filterNode.length) {
              this.curList = [{
                 label: '一级 1',
                 children: filterNode
                 }] 
           }else {
             this.curList = []
           }
       },
posted @ 2020-12-25 18:31  特兰克斯丶  阅读(1042)  评论(0编辑  收藏  举报