侧边菜单、组织架构这类数据天然是树形。与其用模板写死层级循环,不如让组件自己调用自己:一个组件渲染当前层,发现 children 就再渲染一层自己,任意深度都能覆盖。
实现思路
MenuNode 接收 nodes 数组渲染 ul/li;节点带 children 时模板内再写一个 MenuNode 并把子节点传入。Vue3 中 SFC 会按文件名隐式自引用,无需额外 import。
组件代码
<template>
<ul>
<li v-for="item in nodes" :key="item.id">
<div class="node" @click="emit("select", item)">
{{ item.name }}
</div>
<MenuNode
v-if="item.children && item.children.length"
:nodes="item.children"
@select="emit("select", $event)" />
</li>
</ul>
</template>
<script setup>
defineProps({
nodes: { type: Array, default: () => [] }
});
const emit = defineEmits(["select"]);
</script>使用示例
父组件 import MenuNode 后传根数组即可;点击任意节点通过 @select 拿到整行数据,在父组件里做高亮或路由跳转。
扩展思路
- 把 ul/li 换成 el-menu 组件并绑定 index 即可驱动菜单导航;
- 有收起展开需求时在节点上维护 open 状态,点击箭头切换;
- 默认展开层级可用 defaultOpenLevels prop 由父组件控制。
小结
递归组件一劳永逸解决任意深度树渲染,配合事件冒泡式派发,父子间通信也保持单向数据流,是导航与组织树的标准解法。
评论(0)
暂无评论,快来抢沙发吧~