前端简便式动态路由,实现多角色登录不同菜单

本文的动态路由是由前端实现的,因为本项目有多角色登录同一平台,但是又不想涉及后端,所以是简便式的动态路由与动态菜单

1. 步骤

  1. 准备路由数组
  2. 新增方法,动态修改路由数组部分参数
  3. 通过router动态拼接路由
  4. 通过路由数组动态生成菜单

2. 路由数组

export const routes = [
    {
        path: "/system",
        name: "System",
        component: () => import("@/layout/Index.vue"),
        meta: {
            title: "系统管理",
            hide: true,
            icon: "Setting",
        },
        children: [
            {
                path: "/user",
                component: () => import("@/views/system/user/Index.vue"),
                meta: {
                    title: "用户管理",
                    hide: true,
                    icon: "User",
                },
            },
            {
                path: "/notice",
                component: () => import("@/views/system/notice/Index.vue"),
                meta: {
                    title: "公告管理",
                    hide: true,
                    icon: "ChatLineSquare",
                },
            },
        ]
    },
    {
        path: "/message",
        name: "Message",
        component: () => import("@/layout/Index.vue"),
        meta: {
            title: "信息管理",
            hide: true,
            icon: "ChatDotSquare",
        },
        children: [
            {
                path: "/goods_type",
                component: () => import("@/views/information_manager/goods_type/Index.vue"),
                meta: {
                    title: "商品分类管理",
                    hide: true,
                    icon: "Goods",
                },
            },
            {
                path: "/business",
                component: () => import("@/views/information_manager/business/Index.vue"),
                meta: {
                    title: "商家信息管理",
                    hide: true,
                    icon: "UserFilled",
                },
            },
        ]
    },
]

// 根据某些条件动态修改路由数组部分数据
export const updateRoute = () => {
    const user = JSON.parse(localStorage.getItem("user")) // 获取用户数据
    const flag = user && user.role === "ADMIN"  // 判断条件:登录账号并且账号是管理员
    routes.forEach(item => { // 用户登录了并且登录的是管理员账号,才会显示所有菜单,反之隐藏部分菜单
        item.meta.hide = flag; 
        if (item.children.length > 0) { // 如果一级路由还有子路由,继续循环更新路由数组
            item.children.forEach(children => {
                children.meta.hide = flag
            })
        }
    })
}

3. 动态拼接

import {createRouter, createWebHistory} from 'vue-router';
import {routes} from "@/router/routes.ts";

const router = createRouter({
    history: createWebHistory(),
    routes: [
        {
            path: "/",
            name: "Layout",
            component: () => import("@/layout/Index.vue"),
            redirect: '/home',
            meta: {
                title: "",
                hide: false,
            },
            children: [
                {
                    path: "/home",
                    component: () => import("@/views/system/home/Index.vue"),
                    name: "home",
                    meta: {
                        title: "主页",
                        hide: true,
                        icon: "House",
                    },
                },
            ]
        },
        {
            path: '/login',
            component: () => import('@/views/login/Index.vue'),
            name: 'Login',
            meta: {
                title: "登录",
                hide: false,
            },
        },
        {
            path: '/404',
            component: () => import('@/views/404/Index.vue'),
            name: '404',
            meta: {
                title: "404",
                hide: false,
            },
        },
        {
            path: "/:pathMatch(.*)*",
            redirect: "/404",
            name: "Any",
            meta: {
                title: "任意路由",
                hide: false,
            },
        }
    ]
})

// 动态拼接路由数组
const setRoute = () => {
    routes.forEach(item => {
        router.addRoute(item) // 添加一级路由
        if (item.children.length > 0) { // 如果拥有二级路由
            item.children.forEach(children => {
                router.addRoute(item.name, children) // 将二级数组拼到一级路由中,如 {item, children:[children]}
            })
        }
    })
}
setRoute()

export default router;

4. 动态生成菜单

<script lang="ts" setup>
import { useRouter } from "vue-router";
import {updateRoute} from "@/router/routes.ts";

const router = useRouter();

// 页面变量
const menuList = router.getRoutes()
updateRoute()

// 事件定义
const pushPath = (path: string) => { // 点击导航栏按钮对应跳转到页面
    router.push(path)
}
</script>

<template>
    <div v-for="menu in menuList" :key="menu.path">
        <!--        没有子路由            -->
        <div v-if="menu.meta.hide">
            <el-menu-item v-if="!menu.children" :index="menu.path" @click="pushPath(menu.path)">
                <el-icon>
                    <component :is="menu.meta.icon"/>
                </el-icon>
                <template #title>
                     <span>
                         {{ menu.meta.title }}
                     </span>
                </template>
            </el-menu-item>
        </div>
        <!--        只有一个子路由,不显示父路由           -->
        <div v-if="menu.children && !menu.meta.hide">
            <el-menu-item v-if="menu.children.length == 1" :index="menu.children[0].path"
                          @click="pushPath(menu.children[0].path)">
                <template #title>
                    <el-icon>
                        <component :is="menu.children[0].meta.icon"/>
                    </el-icon>
                    <span>
                        {{ menu.children[0].meta.title }}
                    </span>
                </template>
            </el-menu-item>
        </div>
        <!--        只有一个子路由,显示父路由           -->
        <div v-if="menu.children && menu.meta.hide">
            <el-sub-menu
                    v-if="menu.children.length == 1"
                    :index="menu.children[0].path"
            >
                <template #title>
                    <el-icon>
                        <component :is="menu.meta.icon"/>
                    </el-icon>
                    <span> {{ menu.meta.title }} </span>
                </template>
                <el-menu-item-group>
                    <el-menu-item :index="menu.children[0].path" @click="pushPath(menu.children[0].path)">
                        <template #title>
                            <el-icon>
                                <component :is="menu.children[0].meta.icon"/>
                            </el-icon>
                            <span> {{ menu.children[0].meta.title }} </span>
                        </template>
                    </el-menu-item>
                </el-menu-item-group>
            </el-sub-menu>
        </div>
        <!--      多个子路由              -->
        <div v-if="menu.meta.hide">
            <el-sub-menu
                    :index="menu.path"
                    v-if="menu.children && menu?.children.length > 1"
            >
                <template #title>
                    <el-icon>
                        <component :is="menu.meta.icon"/>
                    </el-icon>
                    <span> {{ menu.meta.title }} </span>
                </template>
                <el-menu-item-group v-for="menuChildren in menu.children">
                    <el-menu-item v-if="menuChildren.meta.hide" :index="menuChildren.path" @click="pushPath(menuChildren.path)">
                        <template #title>
                            <el-icon>
                                <component :is="menuChildren.meta.icon"/>
                            </el-icon>
                            <span> {{ menuChildren.meta.title }} </span>
                        </template>
                    </el-menu-item>
                </el-menu-item-group>
            </el-sub-menu>
        </div>
    </div>
</template>

<style scoped>

</style>
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Vue 3前端项目中,实现动态路由导航菜单的思路是,在系统提供默认的路由后,登录后读取菜单/路由数据进行加载。可能会出现默认路由与动态路由有重叠的情况,解决方法是覆盖。菜单与路由数据可以合并为一个数据结构。 一般来说,前端项目中的路由需要动态注册。因为菜单可能在管理系统中维护,还需要与权限绑定。用户登录后,需要动态展示菜单菜单通常与路由相关联,因此,路由需要动态注册。 具体实现的步骤如下: 1. 创建一个名为setup.js的文件,用于组装路由和菜单。 2. 导入默认路由和统一命名的首页路由项。 3. 导入具体业务系统的路由。 4. 在导出的函数中,获取动态路由。可以从指定文件加载或从后端获取。 5. 对齐首页路由项,即使默认路由与业务路由的首页保持一致的命名。 6. 遍历动态路由项,并使用router.addRoute()方法添加动态路由。 下面是一个示例代码: ```javascript import fixItems from "./default"; // 默认路由 import { HomeName } from "./default"; // 统一命名首页路由项 import projectItems from "@/modules/router"; // 具体业务系统的路由 export default (router) => { // 获取动态路由 const dynaItems = getDynamicItems(); // 对齐首页路由项 adpatHome(HomeName, dynaItems); // 添加动态路由 dynaItems.forEach((value) => { router.addRoute(value); }); }; const getDynamicItems = () => { /* 获取动态路由,从指定文件加载或从后端获取 */ return projectItems; }; // 默认路由与业务路由对齐首页的路由信息 // 所谓对齐,就是大家的name保持一致,这样才能保证动态加入的路由项,覆盖掉前面的path和name相同的路由 const adpatHome = (HomeName, dynaItems) => { let home = dynaItems.filter((item) => { return item.path === "/"; }); if (home.length > 0 && home

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值