一、需求背景
项目中使用了导航菜单管理模块,通过该模块够随时添加、删除导航节点。即左侧导航菜单展示的数据是动态可变的,编写前端导航组件时无法得知导航节的点数量,也无法预设导航节点的名称和类型。
二、实现代码
1、NavigationMenu.vue组件:作为父组件遍历NodeList,node.type=1时为导航节点添加路由;
node.type=0时嵌套ChildrenNode.vue子组件。
<template>
<el-menu>
<div v-for="node in NodeList.value" :key="node.id">
<router-link v-if="node.type===1" :to="node.path">
<el-menu-item>{{ node.nodeName }}</el-menu-item>
</router-link>
<el-sub-menu v-if="node.type===0">
<template #title>{{ node.nodeName }}</template>
<ChildrenNode :ChildrenNodeList="node.childrenNodes"></ChildrenNode>
</el-sub-menu>
</div>
</el-menu>
</template>
<script setup>
import axios from 'axios';
import { reactive, ref } from 'vue'
import ChildrenNode from './ChildrenNode.vue'
const NodeList = reactive([]);
axios.get('https://localhost:7106/NavigationMenu/GetNavigationMenu').then(res => { NodeList.value = res.data.childrenNodes;})
</script>
NodeList是从后端请求得到的json数据。type=0表示该节点为”叶子节点“,叶子节点具path属性;type=1表示该节点是”非叶子节点“,非叶子节点具有子节点数组。
{
"id": 2,
"nodeName": "系统管理",
"parentId": 1,
"parentName": "根目录",
"priorityLevel": 0,
"childrenNodes": [
{
"id": 10,
"nodeName": "导航菜单管理",
"parentId": 2,
"parentName": "系统设置",
"priorityLevel": 0,
"childrenNodes": [],
"type": 1,
"path": "/home/navigationMenuManage"
},
{
"id": 11,
"nodeName": "人员管理",
"parentId": 2,
"parentName": "系统设置",
"priorityLevel": 0,
"childrenNodes": [],
"type": 1,
"path": "/home/userManage"
}
],
"type": 0,
"path": ""
},
{
"id": 12,
"nodeName": "餐厅管理",
"parentId": 1,
"parentName": "根目录",
"priorityLevel": 1,
"childrenNodes": [
{
"id": 13,
"nodeName": "菜品管理",
"parentId": 12,
"parentName": "餐厅管理",
"priorityLevel": 0,
"childrenNodes": [],
"type": 1,
"path": "/home/cuisineManage"
},
{
"id": 14,
"nodeName": "订单管理",
"parentId": 12,
"parentName": "餐厅管理",
"priorityLevel": 0,
"childrenNodes": [],
"type": 1,
"path": "/home/orderManage"
}
],
"type": 0,
"path": ""
}
2、ChildrenNode.vue组件:作为子组件接收父组件转递的ChildrenNodeList,遍历ChildrenNodeList。当type=0时递归调用当前组件。
<template>
<div v-for="node in ChildrenNodeList">
<router-link v-if="node.type === 1" :to="node.path">
<el-menu-item>{{ node.nodeName }}</el-menu-item>
</router-link>
<el-sub-menu v-if="node.type === 0">
<template #title>{{ node.nodeName }}</template>
<ChildrenNode :ChildrenNodeList="node.childrenNodes"></ChildrenNode>
</el-sub-menu>
</div>
</template>
<script lang="ts">
export default {
setup() {
return {}
},
name: "ChildrenNode",
props: {
ChildrenNodeList: {
type: Array,
required: true
}
}
}
</script>