开始
在js/jsx中,我们可以通过递归的方式来生成一些有规律的dom结构,那么,在Vue模板中,我们能不能递归生成dom呢?答案是肯定的。在Vue中,组件可以递归的调用自己本身,但是有一些条件:
- 该组件要有name属性
- 要确保递归的调用有终止条件,防止内存溢出
Demo
下面为了方便理解递归组件,我写了一个小的demo:
有这么一份数据,我们希望能把它做成像文件树一样的结果
[
{
'name': 'Vue',
'children': [
{
'name': '模板语法'
},
{
'name': '计算属性'
},
{
'name': '生命周期',
'children': [
{
'name': 'beforeCreate'
},
{
'name': 'created'
},
{
'name': 'beforeMount'
},
{
'name': 'mounted'
},
{
'name': 'beforeUpdate'
},
{
'name': 'updated'
},
{
'name': 'beforeDestroy'
},
{
'name': 'destroyed'
}
]
}
]
},
{
'name': 'React',
'children': [
{
'name': 'jsx'
},
{
'name': '生命周期'
}
]
},
{
'name': 'Angular'
}
]
先写我们的树组件Tree.vue
<template>
<li>
<span @click="toggle">
<i v-if="hasChild" class="icon" :class="[open ? 'folder-open': 'folder']"></i>
<i v-if="!hasChild" class="icon file-text"></i>
{{ data.name }}
</span>
<ul v-show="open" v-if="hasChild">
<tree-menu v-for="(item, index) in data.children" :data="item" :key="index"></tree-menu>
</ul>
</li>
</template>
<script>
export default {
name: 'TreeMenu',
props: {
data: {
type: Object,
required: true
}
},
data() {
return {
open: false
}
},
computed: {
hasChild() {
return this.data.children && this.data.children.length
}
},
methods: {
toggle() {
if(this.hasChild) {
this.open = !this.open
}
}
}
}
</script>
<style>
ul {
list-style: none;
margin: 10px 0;
}
li {
padding: 3px 0;
}
li > span {
cursor: pointer;
font-size: 14px;
line-height: 20px;
}
i.icon {
display: inline-block;
width: 20px;
height: 20px;
margin-right: 5px;
background-repeat: no-repeat;
vertical-align: middle;
}
.icon.folder {
background-image: url("../assets/images/folder.svg");
}
.icon.folder-open {
background-image: url("../assets/images/folder-open.svg");
}
.icon.file-text {
background-image: url("../assets/images/file.svg");
}
.tree-menu li {
line-height: 1.5;
}
</style>
可以看到,我们在Tree组件中有个name选项,值为TreeMenu,然后组件内部调用TreeMenu本身,通过v-for来进行递归条件的判断,这就形成了一个递归组件
然后我们在外部App.vue调用Tree组件
<template>
<div class="tree-menu">
<ul v-for="item in data">
<my-tree :data="item"></my-tree>
</ul>
</div>
</template>
<script>
var myData = [
{
'name': 'Vue',
'children': [{
'name': '模板语法'
},
{
'name': '计算属性'
},
{
'name': '生命周期',
'children': [
{
'name': 'beforeCreate'
},
{
'name': 'created'
},
{
'name': 'beforeMount'
},
{
'name': 'mounted'
},
{
'name': 'beforeUpdate'
},
{
'name': 'updated'
},
{
'name': 'beforeDestroy'
},
{
'name': 'destroyed'
}
]
}
]
},
{
'name': 'React',
'children': [{
'name': 'jsx'
},
{
'name': '生命周期',
'children': []
}
]
},
{
'name': 'Angular'
}
];
import MyTree from './components/Tree'
export default {
components: {
MyTree
},
data() {
return {
data: myData
}
}
}
</script>
最终效果如图:
结束
虽然这篇博客看起来很简单,只是一个小的知识点,但是Vue的递归组件确实是一个非常强大的功能。可以用来实现一些类似文件树、部门树、级联选择这样的组件,在实际业务开发中这些组件也经常用到,还是非常重要的~
原文地址:http://blog.yuantang.site/2017/08/17/Vue递归组件