vue3 + ant-design-vue@3.x 根据路由生成 多级递归嵌套菜单
首先全局注册图标import { createApp } from "vue";import { createFromIconfontCN } from "@ant-design/icons-vue";// 注册远程 iconconst Icon = createFromIconfontCN({// 这个是我自己的图标库,你自己创建要去 iconfont.cn 上创建,看官网教程 https://
·
首先全局注册图标
import { createApp } from "vue";
import { createFromIconfontCN } from "@ant-design/icons-vue";
// 注册远程 icon
const Icon = createFromIconfontCN({
// 这个是我自己的图标库,你自己创建要去 iconfont.cn 上创建,看官网教程 https://next.antdv.com/components/icon-cn#%E8%87%AA%E5%AE%9A%E4%B9%89-font-%E5%9B%BE%E6%A0%87
scriptUrl: "//at.alicdn.com/t/font_3013134_pc3mmckqy1.js", // 在 iconfont.cn 上生成
});
const app = createApp(App);
app.use(router)
.use(antd)
.component("Icon", Icon)
.mount("#app");
配置路由,meta 中的 open 代表此路由是否默认展开
import { createMemoryHistory, createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
export const routes: RouteRecordRaw[] = [
{
path: "/",
name: "index",
component: () => import("@/view/index.vue"),
children: [
{
path: "/dashboard",
name: "dashboard",
meta: {
title: "导航栏",
icon: "icon-dashboard",
},
component: () => import("@/view/dashboard/index.vue"),
},
{
path: "/user",
name: "user",
meta: {
title: "个人信息",
icon: "icon-user",
},
component: () => import("@/view/user/index.vue"),
},
{
path: "/tables",
name: "tables",
meta: {
title: "信息管理",
icon: "icon-table",
open: true,
},
component: () => import("@/view/tables/index.vue"),
children: [
{
path: "user",
name: "tables-user",
component: () => import("@/view/tables/user/index.vue"),
meta: {
title: "用户管理",
icon: "icon-team",
},
},
{
path: "blog",
name: "tables-blog",
component: () => import("@/view/tables/blog/index.vue"),
meta: {
title: "文章管理",
icon: "icon-file-text",
},
},
],
},
{
path: "/setting",
name: "setting",
meta: {
title: "系统设置",
icon: "icon-setting",
},
component: () => import("@/view/setting/index.vue"),
},
{
path: "/:pathMatch(.*)*",
name: "404",
component: () => import("@/view/components/NotFound.vue"),
meta: {
title: "404",
icon: "icon-infos",
},
},
],
},
{
path: "/login",
name: "login",
component: () => import("@/view/login/index.vue"),
},
];
// 菜单主路由
export const menuRoutes = routes.find((r) => r.name === "index");
// 当前路由
export const currentRoute = menuRoutes?.children?.find((r) => r.path === window.location.pathname);
export const router = createRouter({
history: createWebHistory(),
routes: routes,
});
Menus.vue
<template>
<!-- 多级嵌套路由 -->
<a-menu
v-model:selectedKeys="layoutStatus.selectedKeys"
:open-keys="layoutStatus.openKeys"
>
<!-- 遍历菜单路由 -->
<template v-for="route of menuRoutes.children">
<RouteMenus :route="route" />
</template>
</a-menu>
</template>
<script setup lang="ts">
import { ref, reactive, toRefs } from "vue";
import { MenuProps } from "ant-design-vue";
import { menuRoutes } from "../../../route";
import { layoutStatus } from "../../../store/status";
import RouteMenus from "./RouteMenus.vue";
interface MenusProps extends MenuProps {}
withDefaults(defineProps<MenusProps>(), {});
</script>
<style scope lang="less"></style>
RouteMenus.vue 嵌套路由
<template>
<!-- 如果存在子路由 -->
<template v-if="route.children">
<a-sub-menu :key="route.name" :title="route.meta?.title || '未命名'">
<template #icon>
<Icon v-if="route.meta?.icon" :type="route.meta.icon" />
</template>
<template v-for="children of route.children">
<!-- 递归 -->
<RouteMenus :route="children" />
</template>
</a-sub-menu>
</template>
<template v-else>
<a-menu-item :key="route.name" @click="router.push(route.path)">
<Icon v-if="route.meta?.icon" :type="route.meta.icon" />
<span class="nav-text"> {{ route.meta?.title || "未命名" }} </span>
</a-menu-item>
</template>
</template>
<script setup lang="ts">
import { ref, reactive, toRefs } from "vue";
import { RouteRecordRaw } from "vue-router";
import { router } from "../../../route";
interface RouteMenusProps {
route: RouteRecordRaw;
}
const props = withDefaults(defineProps<RouteMenusProps>(), {});
const {} = toRefs(props);
</script>
<style scope lang="less"></style>
效果
现在可以直接在路由动态修改菜单,或者使用远程数据
更多推荐
已为社区贡献9条内容
所有评论(0)