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 = []
           }
       },


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM