對於一些有規律的DOM結構,若是咱們再一遍遍的編寫一樣的代碼,顯然代碼是比較繁瑣和不科學的,並且本身的工做量會大大增長,git
那麼有沒有一種方法來解決這個問題呢?docker
答案是確定的,咱們能夠經過 遞歸 方式來生成這個結構,固然在 Vue 模板中也是能夠實現的,咱們能夠在 Vue 的組件中調用本身自己,這樣就能達到目的。bash
固然,在 Vue 中,組件能夠遞歸的調用自己,可是有一些條件:架構
name
屬性爲了方便理解遞歸組件,我寫了一個小小的 Demo:組件化
下面有這樣一個數據,咱們但願把它作成一個文件樹同樣的結果:ui
treeData: {
title: "Web全棧架構師",
children: [
{
title: "Java架構師"
},
{
title: "JS高級",
children: [
{
title: "ES6"
},
{
title: "動效"
}
]
},
{
title: "Web全棧",
children: [
{
title: "Vue訓練營",
expand: true,
children: [
{
title: "組件化"
},
{
title: "源碼"
},
{
title: "docker部署"
}
]
},
{
title: "React",
children: [
{
title: "JSX"
},
{
title: "虛擬DOM"
}
]
},
{
title: "Node"
}
]
}
]
}
複製代碼
先寫一個樹組件(Item):this
<template>
<li>
<!-- 點擊摺疊展開 -->
<div @click="toggle">
<!-- 顯示內容 -->
{{model.title}}
<!-- 顯示摺疊展開的圖標,若是沒有下級目錄的話,則不顯示 -->
<span v-if="isFolder">[{{open?'-':'+'}}]</span>
</div>
<!-- 控制是否顯示下級目錄 -->
<ul v-show="open" v-if="isFolder">
<!-- 重點代碼,調用自身,實現遞歸,綁定數據 -->
<Item v-for="model in model.children" :model="model" :key="model.title"></Item>
</ul>
</li>
</template>
<script>
export default {
name: "Item",
// 若是想使用此組件,則須要傳遞的數據
props: {
model: {
type: Object,
required: true
}
},
data() {
return {
// 默認不顯示下級目錄
open: false
};
},
computed: {
// 控制是否有下級目錄和顯示下級目錄
isFolder() {
return this.model.children && this.model.children.length;
}
},
methods: {
// 點擊摺疊展開的方法
toggle() {
if (this.isFolder) {
this.open = !this.open;
}
}
}
};
</script>
複製代碼
具體代碼的功能已在上面註釋spa
再次強調,這個組件必需要含有 name 這個屬性,若是沒有 name 這個屬性會形成控件自身不能調用自身,並且調用的時候最好綁定一個 key 值,由於這個 key 值是惟一的標識code
另外須要注意,當遞歸組件的時候,須要有一個條件來終止遞歸,在這裏使用 v-for 隱形條件終止遞歸component
而後在外部組件引入這個組件,並綁定數據使用,以下:
<template>
<div>
<ul>
<!-- 使用這個組件,並綁定數據 -->
<Item :model="treeData"></Item>
</ul>
</div>
</template>
<script>
// 導入遞歸組件
import Item from "./views/Item";
export default {
name: "App",
data() {
return {
// 須要實現遞歸的數據,上面已經給出
treeData: {...
}
};
},
components: {
// 註冊組件
Item
}
};
</script>
複製代碼
上面的代碼已經實現了一個遞歸樹形結構了,展現效果以下:
後面是 + 號 的能夠點擊展開,是 - 號 的能夠點擊摺疊
雖然這篇博客看起來很簡單,只是一個小的知識點,可是Vue的遞歸組件確實是一個很是強大的功能。能夠用來實現一些相似文件樹、部門樹、級聯選擇這樣的組件,在實際業務開發中這些組件也常常用到,仍是很是重要的~