vue遞歸組件的用法

2019-06-24 18:12:30發布 作者:姓趙的趙先生? 來源:https://blog.csdn.net/badmoonc/article/details/80380557?
概念:
組件是可以在它們自己的模板中調用自身的。不過它們只能通過 name 選項來做這件事。

之前在寫組件時總有些疑惑,為什么export default導出的對象中有個name屬性,今天看過遞歸組件之后,才發現這個name屬性的一個比較重要的作用。(當然。name屬性的還有其他的用處)。

用法:
1、首先我們要知道,既然是遞歸組件,那么一定要有一個結束的條件,否則就會使用組件循環引用,最終出現“max stack size exceeded”的錯誤,也就是棧溢出。那么,我們可以使用v-if="false"作為遞歸組件的結束條件。當遇到v-if為false時,組件將不會再進行渲染。

既然要用遞歸組件,那么對我們的數據格式肯定是需要滿足遞歸的條件的。就像下邊這樣,這是一個樹狀的遞歸數據。

    [
      {
        "name": "黃燜雞米飯111111111",
        cList: [
          { "name": "二級黃燜雞" },
          {
            "name": "one chicken",
            cList: [{ "name": '三級黃燜雞3333', cList: [{ "name": "四級黃燜雞" }] }]
          }
        ]
      },
      { "name": "2222222222" },
      {
        "name": "黃燜雞米飯33333333", cList: [
          { "name": "二級黃燜雞" },
          { "name": "one chicken" }
        ]
      },
    ]
接下來,我們就用這個樹狀數據,做一個簡單版的樹狀菜單。樹狀菜單,也是遞歸組件最常用的方法之一。

實踐案例:
首先,我們先創建一個tree組件,這個組件作為使用遞歸組件的父組件,我們來看下具體寫法

<template>
  <div>
    <my-trees :list="list"></my-trees>
  </div>
</template>
<script>
import myTrees from './treeMenus'
export default {
  components: {
    myTrees
  },
  data () {
    return {
      list: [
        {
          name: '黃燜雞米飯111111111',
          cList: [
            { name: '二級黃燜雞' },
            {
              name: 'one chicken',
              cList: [
                { name: '三級黃燜雞3333', cList: [{ name: '四級黃燜雞' }] }
              ]
            }
          ]
        },
        { name: '2222222222' },
        {
          name: '黃燜雞米飯33333333',
          cList: [{ name: '二級黃燜雞' }, { name: 'one chicken' }]
        }
      ]
    }
  },
  methods: {}
  
}
</script>
ok,可以看到,<my-trees />就是我們說的遞歸組件,當使用它時,只需要把上邊我們定義好的數據通過props的方式傳進去即可。

接下來,遞歸組件接收到了父組件傳遞的數據,就可以進行遞歸啦,我們來看下邊的實現:

<template>
  <ul>
    <li v-for="(item,index) in list " :key="index">
      <p>{{item.name}}</p>
      <tree-menus :list="item.cList"></tree-menus>
    </li>
  </ul>
</template>
 <style>
   ul{
    padding-left: 20px!important;
   }
 </style>
<script>
    export default{
        name:'treeMenus',
        props:{
            list: Array
        }
    }
</script>
注意本文開頭所說,name屬性的使用(你可以把它當作從import導入了一個組件并注冊,我們在temlpate可以使用<tree-menus></tree-menus>使用子組件自身進行遞歸了)

總結:
通過props從父組件拿到數據,遞歸組件每次進行遞歸的時候都會tree-menus組件傳遞下一級cList數據,(大家可以想象一下整個過程),整個過程結束之后,遞歸也就完成了,當然,這段代碼只是簡單的做了下遞歸組件的使用。對于折疊樹狀菜單來說,我們一般只會去渲染一級的數據,當點擊一級菜單時,再去渲染一級菜單下的結構,如此往復。那么v-if就可以實現我們的這個需求,當v-if設置為false時,遞歸組件將不會再進行渲染,設置為true時,繼續渲染。

最后也為大家準備了一個樹狀折疊菜單的遞歸組件實現方式,沒有樣式大家不要介意啦~

<template>
 
  <ul>
    <li v-for="(item,index) in list" :key="index">
      <p @click="changeStatus(index)">{{item.name}}</p>
      <tree-menus v-if="scopesDefault[index]" :list="item.cList"></tree-menus>
    </li>
  </ul>
 
</template>
 <style>
ul {
  margin-top: 50px;
  padding-left: 20px !important;
}
</style>
<script>
// import treeMenus from './treeMenu2.vue'
export default {
  name: 'treeMenus',
  props: {
    list: Array
  },
  data() {
    return {
      scopesDefault: [],
      scopes: []
    }
  },
 
  methods: {
    changeStatus(index) {
      console.log(index);
      if (this.scopesDefault[index] == true) {
        this.$set(this.scopesDefault, index, false)
      } else {
        this.$set(this.scopesDefault, index, this.scopes[index])
      }
    },
    scope() {
      this.list.forEach((item, index) => {
        this.scopesDefault[index] = false
        if ('cList' in item) {
          this.scopes[index] = true
          console.log(item, index)
        } else {
          this.scopes[index] = false
        }
      })
      console.log(this.scopesDefault)
    }
  },
  created() {
    this.scope()
  }
}
</script>
 
 
上海二八杠单人操作