导航菜单主页面
<template><div :class="collapsed ? 'shrink' : 'open'"><a-buttontype="primary"@click="toggleCollapsed"class="buttonOpen":style="{ marginLeft: collapsed ? '18px' : '10px' }"><p v-if="collapsed" title="展开菜单"><MenuUnfoldOutlined /></p><p v-else title="收拢菜单"><MenuFoldOutlined /></p></a-button><a-menuv-model:openKeys="openKeys"mode="inline"theme="dark":inline-collapsed="collapsed"class="menu-class"><template v-for="item in routerList" :key="item.name"><template v-if="item.meta.hidden"> // 首先根据meta里面的hidden属性判断是否显示,比如登录页面就不需要显示<template v-if="!item.children"> // 如果没有子菜单,显示的就应该是第一层菜单<a-menu-item :key="item.name"><PieChartOutlined /><span>{{item.meta.title }}</span></a-menu-item></template><template v-else> // 调用递归子组件<sub-menu :menu-info="item" :key="item.name" /></template></template></template></a-menu></div></template><script lang="ts">import {defineComponent, reactive, toRefs } from "vue";import {MenuFoldOutlined,MenuUnfoldOutlined,PieChartOutlined,} from "@ant-design/icons-vue";import SubMenu from "./SubMenu.vue";import {useRoute, useRouter } from "vue-router";export default defineComponent({components: {"sub-menu": SubMenu,MenuFoldOutlined,MenuUnfoldOutlined,PieChartOutlined,},setup() {const router = useRouter();const route = useRoute();const data = reactive({collapsed: false,routerList: router.options.routes,openKeys: [],selectedKeys: [],toggleCollapsed() {if (!data.collapsed) (data.openKeys as any) = [];else (data.openKeys as any) = route.fullPath.split("/").slice(1);data.collapsed = !data.collapsed;},});return {...toRefs(data),};},});</script><style lang="scss" scoped>.shrink {width: 80px;transition: width 0.3s;}.open {width: 256px;transition: width 0.3s;}.menu-class {height: calc(100vh - 50px);}.buttonOpen {margin: 6px 0;// transition: all 0.3 !important;}</style>
递归子组件
<template><a-sub-menu :key="menuInfo.name" v-bind="$attrs"><template #title><span><MailOutlined /><span>{{menuInfo.meta.title }}</span></span></template><template v-for="item in menuInfo.children" :key="item.name"><template v-if="item.meta.hidden"><template v-if="!item.children"><a-menu-item :key="item.name"><PieChartOutlined /><span>{{item.meta.title }}</span></a-menu-item></template><template v-else> // 递归调用自身组件<sub-menu :menu-info="item" :key="item.name" /></template></template></template></a-sub-menu></template><script lang="ts">import {defineComponent } from "vue";import {Menu } from 'ant-design-vue';import {PieChartOutlined, MailOutlined } from "@ant-design/icons-vue";export default defineComponent({name: "SubMenu",components: {PieChartOutlined,MailOutlined,},props: {...Menu.SubMenu.props,menuInfo: {type: Object,default: () => ({}),},},});</script><style lang="scss" scoped></style>
截图一个router的写法
如果有根据后台获取展示菜单,则继续在meta中添加对应属性匹配即可,类似图上umark。