前言
Vue递归组件用于在组件内部调用自身,以实现树状结构或嵌套结构的渲染。
常见用途
- 树形菜单:可以递归渲染多级菜单项。
- 文件目录:适用于展示文件夹和文件的嵌套结构。
- 评论回复:用于显示具有嵌套回复的评论列表。
- 组织结构图:渲染公司或组织的层级关系。
示例预览
示例代码
Parent.vue
<script setup lang="ts">
import ChildNode from './ChildNode.vue';
const treeData = [
{
"id": "1",
"children": [
{
"id": "1-1",
"children": [
{
"id": "1-1-1",
"children": []
}
]
},
{
"id": "1-2",
"children": []
}
]
},
{
"id": "2",
"children": [
{
"id": "2-1",
"children": []
},
{
"id": "2-2",
"children": []
}
]
}
]
</script>
<template>
<ChildNode v-for="node in treeData"
:key="node.id"
:level="1"
:data="node"
isVisible
/>
</template>
ChildNode.vue
<script setup lang="ts">
import { ref } from 'vue'
type Data = {
id: string
children?: Data[]
}
defineProps<{
level: number,
data: Data
isVisible: boolean
}>()
const isExpand = ref(true)
const chnageExpand = () => {
isExpand.value = !isExpand.value
}
</script>
<template>
<div class="tree-node" v-if="isVisible" >
<span v-if="level > 1" :style="{ paddingLeft: (level - 1) * 25 + 'px' }"></span>
<button class="expand-btn" v-if="data.children?.length" @click="chnageExpand">
{{ isExpand ? '-' : '+' }}
</button>
<span class="expand-btn" v-else style="visibility: hidden;"></span>
<div class="tree-node-cotent">
{{ data.id }}
</div>
</div>
<template v-if="data.children?.length">
<ChildNode v-for="node in data.children" :key="node.id" :level="level + 1" :data="node" :isVisible="isVisible && isExpand" />
</template>
</template>
<style>
.tree-node {
display: flex;
align-items: center;
}
.expand-btn {
margin-right: 5px;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
}
.tree-node-cotent {
border: 1px solid #ddd;
padding: 5px;
margin-bottom: 4px;
flex-grow: 2;
}
</style>
总结
- 一个单文件组件可以通过它的
文件名
被其自己所引用
。 - 递归组件的核心在于其自我调用能力,允许在数据结构
不确定深度
的情况下进行动态渲染
。