在vue中,组件是可以在它们自己的模板中调用自身的,这称为递归组件,比如Tree组件就是常见的递归组件。要设计一个递归组件,需满足两个条件:
- 组件必须有name选项
- 组件的递归调用有终止条件
根据这个思路,我们来看看如何设计一个Tree组件:
1、实现TreeItem
<!--TreeItem.vue-->
<template>
<li class="tree-item-comp">
<div class="tree-item-hd" @click="toggle">
{{model.title}}
<span class="toggle-icon" v-if="isFolder">[{{open? '-': '+'}}]</span>
</div>
<!-- 递归子Item -->
<!-- 递归组件关键点二:递归有一个明确终止的条件 -->
<ul v-if="isFolder" v-show="open">
<tree-item v-for="model in model.children"
:model="model"
:key="model.title">
</tree-item>
</ul>
</li>
</template>
<script>
export default {
// 设计递归组件关键点一:必须有'name'选项
name: "TreeItem",
props: {
model: {
type: Object
}
},
data() {
return {
open: false
};
},
computed: {
<!--如果this.model.children有值,说明它还有次级节点-->
isFolder() {
return this.model.children && this.model.children.length;
}
},
methods: {
toggle() {
if (this.isFolder) {
this.open = !this.open;
}
}
}
};
</script>
2、实现Tree
<!--Tree.vue-->
<template>
<div class="tree-comp">
<ul>
<tree-item :model="treeData"></tree-item>
</ul>
</div>
</template>
<script>
import TreeItem from "@/components/Tree/TreeItem";
export default {
name: "Tree",
components: {
TreeItem
},
data() {
return {
treeData: {
title: "Web全栈",
children: [
{
title: "React"
},
{
title: "Vue全家桶",
children: [
{
title: "ElementUI"
},
{
title: "Vue-Router"
},
{
title: "Vuex"
}
]
},
{
title: "Node",
children: [
{
title: "数据持久化",
children: [
{
title: "mysql"
},
{
title: "mongodb"
},
{
title: "redis"
}
]
},
{
title: "Node框架",
children: [
{
title: "express"
},
{
title: "koa"
}
]
},
{
title: "docker"
}
]
}
]
}
};
}
};
</script>