1.原理
通过定义组件name,如:name:Node
,在template里面直接引用自身 <Node></Node>
2.代码实现
//Node.vue
<template>
<div>
<h3>{{ data.name }}</h3>
<!-- 有条件嵌套 -->
<Node v-for="n in data.children" :key="n.name" :data="n"> </Node>
</div>
</template> <script>
export default {
name: "Node", // name对递归组件是必要的
props: {
data: {
type: Object,
require: true,
},
},
};
</script>
//NodeTest.vue
<template>
<div><Node :data="folder"></Node></div>
</template> <script>
import Node from "@/Node.vue";
export default {
components: {
Node,
},
data() {
return {
// 树形结构的数据
folder: {
name: "vue-study",
children: [
{ name: "一级文件夹A", children: [{ name: "二级文件夹" }] },
{ name: "一级文件夹B" },
],
},
};
},
};
</script>
复制代码
3.树形菜单实现
//index.vue
<template>
<Tree :data="treeData"></Tree>
</template>
<script>
import Tree from "@/components/recursion/Tree.vue";
export default {
data() {
return {
treeData: [
{
title: "根节点",
children: [
{
title: "一级AAA"
},
{
title: "一级BBBB",
children: [
{
title: "二级11"
},
{
title: "二级22"
}
]
},
{
title: "一级CCC",
children: [
{
title: "二级666",
expand: true,
children: [
{
title: "三级111"
},
{
title: "三级222"
},
{
title: "三级333"
}
]
},
{
title: "二级777",
children: [
{
title: "三级888"
},
{
title: "三级999"
}
]
},
]
}
]
}
]
};
},
components: {
Tree
}
};
</script>
//Tree.vue
<template>
<div class="tree">
<TreeNode v-for="item in data" :key="item.title" :model="item"></TreeNode>
</div>
</template>
<script>
import TreeNode from "@/components/recursion/TreeNode.vue";
export default {
props: {
data: {
type: Array,
required: true
}
},
components: {
TreeNode
}
};
</script>
<style scoped>
.tree {
text-align: left;
}
</style>
//TreeNode.vue
<template>
<div>
<div @click="toggle" :style="{paddingLeft: (level-1)+'em'}">
<label>{{model.title}}</label>
<span v-if="isFolder">[{{open ? '-' : '+'}}]</span>
</div>
<div v-show="open" v-if="isFolder">
<tree-node class="item" v-for="model in model.children"
:model="model" :key="model.title"
:level="level + 1"></tree-node>
</div>
</div>
</template>
<script>
export default {
name: "tree-node",
props: {
model: Object,
level: {
type: Number,
default: 1
}
},
data: function() {
return {
open: false
};
},
computed: {
isFolder: function() {
return this.model.children && this.model.children.length;
}
},
methods: {
toggle: function() {
if (this.isFolder) {
this.open = !this.open;
}
},
}
};
</script>
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END