vue3 + [email protected] 根据路由生成 多级递归嵌套菜单

首先全局注册图标

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>

效果
vue3 + ant-design-vue@3.x 根据路由生成 多级递归嵌套菜单_第1张图片
现在可以直接在路由动态修改菜单,或者使用远程数据

你可能感兴趣的:(Vue,【基础】,vue.js,javascript,前端,ant-design-vue)