前言
在之前一篇《Vue 中使用渲染函数 render 实现无限节点的树》中我们介绍了如何使用 render 函数中的 h 函数来实现无限节点树的渲染,但这种方式有很多小伙伴们可能使用起来不是很习惯。有没有一种更加直观的方式来实现呢?其实是有的,就是我们可以递归调用树节点组件自身实现无限节点的树。
这种方式跟使用 jsx 可以轻松使用递归实现有点类似。废话不多数,先上在线 Demo,Github 上源码地址
代码分析
树节点组件 TreeNode.vue 代码如下:
<template>
<li>
<a
:class="{'open': isOpen && data.children.length > 0, 'close': !isOpen && data.children.length > 0}"
href="javascript:void(0);"
class="name"
@click="isOpen = !isOpen"
>{{ data.name }}</a>
<ul :class="{'hide': !isOpen}">
<tree-node
v-for="item in data.children"
:key="item.id"
:data="item"
/>
</ul>
</li>
</template>
<script>
export default {
name: 'TreeNode',
props: {
data: {
type: Object,
default: () => {
return {
id: String(new Date().getTime() + Math.floor(9999 * Math.random())),
name: '',
children: []
}
}
}
},
data () {
return {
isOpen: false
}
}
}
</script>
生成树页面 TreeDemoII.vue 代码如下:
<template>
<article class="pageview">
<header class="header fixed">
<div class="container">
<a
class="back back_ico"
href="javascript:void(0);"
@click="goBack"
></a><span class="title">{{ msg }}</span>
</div>
</header>
<section class="main">
<div
id="menu"
class="clearfix menu"
>
<ul>
<tree-node
v-for="item in data"
:key="item.id"
:data="item"
/>
</ul>
</div>
</section>
</article>
</template>
<script>
import TreeNode from '../components/TreeNode'
import { goBack } from '../util/tools'
export default {
name: 'TreeDemoII',
components: {
TreeNode
},
data () {
return {
msg: 'Tree Demo II',
data: [
{
id: 0,
name: '节点1',
children: [
{
id: 1,
name: '节点1-1',
children: []
},
{
id: 2,
name: '节点1-2',
children: [
{
id: 7,
name: '节点1-2-1',
children: [
{
id: 10,
name: '节点1-2-1-1',
children: []
},
{
id: 11,
name: '节点1-2-1-2',
children: []
}
]
},
{
id: 8,
name: '节点1-2-2',
children: []
}
]
}
]
},
{
id: 3,
name: '节点2',
children: [
{
id: 4,
name: '节点2-1',
children: []
},
{
id: 5,
name: '节点2-2',
children: []
}
]
},
{
id: 6,
name: '节点3',
children: []
}
]
}
},
methods: {
goBack: goBack
},
}
</script>
<style lang="scss" scoped>
.menu {
/deep/ {
.hide {
display: none !important;
}
a {
color: #000;
padding: 10px 0;
display: block;
}
ul {
padding-left: 0px;
}
li {
list-style: none;
margin-left: 30px;
border-left: 1px dashed #000;
.name:before {
content: "--";
}
.close:after {
content: "[+]";
margin-left: 10px;
}
.open:after {
content: "[-]";
margin-left: 10px;
}
}
}
}
</style>
总结
这里主要是使用递归调用的思想来实现树节点,Vue 组件是支持在本组件中调用本组件的,这非常有趣,让我们可以更加灵活的实现一些特定场景的功能,比如树、无限菜单等。