在使用element plus 时,最初要使用的就是导航组件了,官网上看到的也就是写死的一级/二级导航,那么如何设计一个无限级且动态的导航呢?毋庸置疑,递归。废话不多说,直接看代码和效果:
代码:
目录结果
SidebarItem.vue
<template><el-menu-item :index="item ? item.url : ''" v-if="!item || !item.children || item.children.length === 0">{{ item?.menuName }}</el-menu-item><el-sub-menu :index="item ? item.id : ''" v-else><template #title><span class="tab">{{ item?.menuName }}</span></template><div v-for="(child, index) in item?.children" :key="index"><template v-if="child.children && child.children.length > 0"><sidebar-item :key="child.id" :item="child" /></template><el-menu-item v-else :index="child.url"><span class="tab sub">{{ child.menuName }}</span></el-menu-item></div></el-sub-menu>
</template><script lang="ts" setup>
import { PropType, toRefs } from 'vue';
import { MenuNode } from '../../../../model/menuNode';const props = defineProps({collapse: {type: Boolean,default: true},item: {type: Object as PropType<MenuNode>,},
});const { item } = toRefs(props);
</script><style lang="scss"></style>
Index.vue
<div class="nav"><el-scrollbar class="scrollbar"><el-menu class="menu" @open="handleOpen" @close="handleClose" mode="horizontal" router><SidebarItem v-for="route in menuList" :key="route.id" :item="route"></SidebarItem></el-menu></el-scrollbar></div>
测试数据:
export default [{'id': '001','parentId': '0','menuName': '首页','url': '/dashboard','sortNo': 1,'icon': 'Aim'},{'id': '002','parentId': '0','menuName': '表格','url': '/charts','sortNo': 4,'icon': 'ArrowDownBold'},{'id': '0021','parentId': '002','menuName': '树状图','url': '/charts/charts1','sortNo': 4,'icon': 'ArrowDownBold'},{'id': '0022','parentId': '002','menuName': '饼状图','url': '/charts/charts2','sortNo': 4,'icon': 'ArrowDownBold'},{'id': '003','parentId': '0','menuName': '测试四级1','url': '/dashboard','menuType': 1,'sortNo': 2,'icon': 'Aim'},{'id': '0031','parentId': '003','menuName': '测试四级2','url': '/dashboard','menuType': 1,'sortNo': 2,'icon': 'Aim'},{'id': '00311','parentId': '0031','menuName': '测试四级3','url': '/dashboard','menuType': 1,'sortNo': 2,'icon': 'Aim'},{'id': '003111','parentId': '00311','menuName': '测试四级4','url': '/dashboard','menuType': 1,'sortNo': 2,'icon': 'Aim'},
];
这里需要将数组转换成树形结构,也附上代码好了(纯手工输出,有bug还望见谅):
/** @Author: zzh* @Date: 2022-03-01 14:39:16* @LastEditors: zzh* @LastEditTime: 2022-04-10 17:13:03* @Description: 数据转换帮助类* @FilePath: \zh-admin\src\utils\dataConvert.ts*/import { MenuNode } from '../model/menuNode';// 由于菜单数据并非一颗树,而是多棵树组成的数据,顾当成由树组成的数组的处理
const convertMenuArrToTree = (array: Array<MenuNode>) => {const rootMenus = array.filter(x => x.parentId === '0');const childrenMenus = array.filter(x => x.parentId !== '0');for (let i = 0; i < rootMenus.length; i++) {if (childrenMenus.find(x => x.parentId === rootMenus[i].id)) {rootMenus[i].children = getRootMenuChild(rootMenus[i].id, childrenMenus);} else {rootMenus[i].children = [];}}return rootMenus;
};const getRootMenuChild = (id: string, childrenMenus: Array<MenuNode>): Array<MenuNode> => {const menus = childrenMenus.filter(x => x.parentId === id);for (let i = 0; i < menus.length; i++) {if (childrenMenus.find(x => x.parentId === menus[i].id)) {menus[i].children = getRootMenuChild(menus[i].id, childrenMenus);} else {menus[i].children = [];}}return menus;
};export {convertMenuArrToTree,
};
展示结果: