概念:
組件是能夠在它們本身的模板中調用自身的。不過它們只能經過 name 選項來作這件事。html
以前在寫組件時總有些疑惑,爲何export default導出的對象中有個name屬性,今天看過遞歸組件以後,才發現這個name屬性的一個比較重要的做用。(固然。name屬性的還有其餘的用處)。vue
用法:
一、首先咱們要知道,既然是遞歸組件,那麼必定要有一個結束的條件,不然就會使用組件循環引用,最終出現「max stack size exceeded」的錯誤,也就是棧溢出。那麼,咱們可使用v-if="false"做爲遞歸組件的結束條件。當遇到v-if爲false時,組件將不會再進行渲染。this
既然要用遞歸組件,那麼對咱們的數據格式確定是須要知足遞歸的條件的。就像下邊這樣,這是一個樹狀的遞歸數據。spa
1 [ 2 { 3 "name": "黃燜雞米飯111111111", 4 cList: [ 5 { "name": "二級黃燜雞" }, 6 { 7 "name": "one chicken", 8 cList: [{ "name": '三級黃燜雞3333', cList: [{ "name": "四級黃燜雞" }] }] 9 } 10 ] 11 }, 12 { "name": "2222222222" }, 13 { 14 "name": "黃燜雞米飯33333333", cList: [ 15 { "name": "二級黃燜雞" }, 16 { "name": "one chicken" } 17 ] 18 }, 19 ]
接下來,咱們就用這個樹狀數據,作一個簡單版的樹狀菜單。樹狀菜單,也是遞歸組件最經常使用的方法之一。code
首先,咱們先建立一個tree組件,這個組件做爲使用遞歸組件的父組件,咱們來看下具體寫法component
1 <template> 2 <div> 3 <my-trees :list="list"></my-trees> 4 </div> 5 </template> 6 <script> 7 import myTrees from './treeMenus' 8 export default { 9 components: { 10 myTrees 11 }, 12 data () { 13 return { 14 list: [ 15 { 16 name: '黃燜雞米飯111111111', 17 cList: [ 18 { name: '二級黃燜雞' }, 19 { 20 name: 'one chicken', 21 cList: [ 22 { name: '三級黃燜雞3333', cList: [{ name: '四級黃燜雞' }] } 23 ] 24 } 25 ] 26 }, 27 { name: '2222222222' }, 28 { 29 name: '黃燜雞米飯33333333', 30 cList: [{ name: '二級黃燜雞' }, { name: 'one chicken' }] 31 } 32 ] 33 } 34 }, 35 methods: {} 36 37 } 38 </script>
ok,能夠看到,<my-trees />就是咱們說的遞歸組件,當使用它時,只須要把上邊咱們定義好的數據經過props的方式傳進去便可。xml
接下來,遞歸組件接收到了父組件傳遞的數據,就能夠進行遞歸啦,咱們來看下邊的實現:htm
1 <template> 2 <ul> 3 <li v-for="(item,index) in list " :key="index"> 4 <p>{{item.name}}</p> 5 <tree-menus :list="item.cList"></tree-menus> 6 </li> 7 </ul> 8 </template> 9 <style> 10 ul{ 11 padding-left: 20px!important; 12 } 13 </style> 14 <script> 15 export default{ 16 name:'treeMenus', 17 props:{ 18 list: Array 19 } 20 } 21 </script>
注意本文開頭所說,name屬性的使用(你能夠把它看成從import導入了一個組件並註冊,咱們在temlpate可使用<tree-menus></tree-menus>使用子組件自身進行遞歸了)對象
總結:
經過props從父組件拿到數據,遞歸組件每次進行遞歸的時候都會tree-menus組件傳遞下一級cList數據,(你們能夠想象一下整個過程),整個過程結束以後,遞歸也就完成了,固然,這段代碼只是簡單的作了下遞歸組件的使用。對於摺疊樹狀菜單來講,咱們通常只會去渲染一級的數據,當點擊一級菜單時,再去渲染一級菜單下的結構,如此往復。那麼v-if就能夠實現咱們的這個需求,當v-if設置爲false時,遞歸組件將不會再進行渲染,設置爲true時,繼續渲染。blog
最後也爲你們準備了一個樹狀摺疊菜單的遞歸組件實現方式,沒有樣式你們不要介意啦~
1 <template> 2 3 <ul> 4 <li v-for="(item,index) in list" :key="index"> 5 <p @click="changeStatus(index)">{{item.name}}</p> 6 <tree-menus v-if="scopesDefault[index]" :list="item.cList"></tree-menus> 7 </li> 8 </ul> 9 10 </template> 11 <style> 12 ul { 13 margin-top: 50px; 14 padding-left: 20px !important; 15 } 16 </style> 17 <script> 18 // import treeMenus from './treeMenu2.vue' 19 export default { 20 name: 'treeMenus', 21 props: { 22 list: Array 23 }, 24 data() { 25 return { 26 scopesDefault: [], 27 scopes: [] 28 } 29 }, 30 31 methods: { 32 changeStatus(index) { 33 console.log(index); 34 if (this.scopesDefault[index] == true) { 35 this.$set(this.scopesDefault, index, false) 36 } else { 37 this.$set(this.scopesDefault, index, this.scopes[index]) 38 } 39 }, 40 scope() { 41 this.list.forEach((item, index) => { 42 this.scopesDefault[index] = false 43 if ('cList' in item) { 44 this.scopes[index] = true 45 console.log(item, index) 46 } else { 47 this.scopes[index] = false 48 } 49 }) 50 console.log(this.scopesDefault) 51 } 52 }, 53 created() { 54 this.scope() 55 } 56 } 57 </script>