Tree 组件是典型的递归组件,其他的诸如菜单组件都属于这一类,也是相当常见的。
Tree 组件最适合的结构是无序列表 ul,创建⼀个递归组件 Item 表示 Tree 选项,如果当前 Item 存在 children,则递归渲染子树,以此类推;同时添加一个标识管理当前层级 item 的展开状态。
Item.vue
<template>
<li>
<div @click="toggle" :class="{ handle: isFolder }">
<!-- 标题 -->
{{ model.title }}
<!-- 有子元素就显示 -->
<span v-if="isFolder">[{{ open ? "-" : "+" }}]</span>
</div>
<!-- 子树 -->
<ul v-show="open" v-if="isFolder" class="list">
<item class="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
}
},
data() {
return {
open: false
};
},
computed: {
isFolder: function() {
return this.model.children && this.model.children.length;
}
},
methods: {
toggle() {
if (this.isFolder) {
this.open = !this.open;
}
}
}
};
</script>
<style scoped lang="less">
.handle {
cursor: pointer;
}
.list {
padding-left: 20px;
}
.item {
line-height: 25px;
}
</style>
index.vue
<template>
<div id="app">
<ul>
<item class="item" :model="treeData"></item>
</ul>
</div>
</template>
<script>
import Item from "./Item";
export default {
name: "app",
data() {
return {
treeData: {
title: "Web全栈架构师",
children: [
{
title: "JavaScript"
},
{
title: "JS高级",
children: [
{
title: "ES6"
},
{
title: "动效"
}
]
},
{
title: "Web全栈",
children: [
{
title: "Vue训练营",
expand: true,
children: [
{
title: "基础知识"
},
{
title: "组件化"
},
{
title: "源码"
}
]
},
{
title: "React",
children: [
{
title: "JSX"
},
{
title: "虚拟DOM"
}
]
},
{
title: "Node"
},
{
title: "WebPack"
}
]
}
]
}
};
},
components: { Item }
};
</script>