Vue递归组件

开始

在js/jsx中,我们可以通过递归的方式来生成一些有规律的dom结构,那么,在Vue模板中,我们能不能递归生成dom呢?答案是肯定的。在Vue中,组件可以递归的调用自己本身,但是有一些条件:

  1. 该组件要有name属性
  2. 要确保递归的调用有终止条件,防止内存溢出

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递归组件

转载于:https://my.oschina.net/prettypice/blog/1512498

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值