Vue 项目中基于后端权限的动态路由实现

首先页面需要准备三个数组:基础路由,完整路由,模拟接口数据

  1. 基础路由也就是静态路由(只有基本页面配置,不包含动态路由的组件。也是接下来用于注册页面的数组)

    // 基础路由(只有基本页面配置,不包含动态路由的组件)
    const baseRoutesWithoutComponents = [
    {
    path: '/',
    name: 'login',
    component: () => import("@/views/Login.vue")
    },
    {
    path: '/404',
    name: '404',
    component: () => import('@/views/notFound.vue')
    },
    {
    path: '/layout',
    name: 'layout',
    component: () => import('@/components/all.vue'),
    children: [] // 初始为空,动态路由将添加到这里
    }
    ];

2.完整路由配置(包含所有可能的页面组件。不能注册这个)

复制代码
// 完整路由配置(包含所有可能的页面组件)
const baseRoutesWithComponents = [
    {
        path: '/',
        name: 'login',
        component: () => import("@/views/Login.vue")
    },
    {
        path: '/404',
        name: '404',
        component: () => import('@/views/notFound.vue')
    },
    {
        path: '/layout',
        name: 'layout',
        component: () => import('@/components/all.vue'),
        children: [
            {
                path: '/home',
                name: '首页',
                id: 1,
                pid: 0,
                component: () => import('@/views/homeView.vue')
            },
            {
                id: 2,
                pid: 0,
                redirect: null,
                path: '/comp',
                name: '门诊',
                component: () => import('@/views/outpatientView.vue'), // 添加父级组件
                children: [
                    {
                        id: 3,
                        pid: 2,
                        redirect: null,
                        component: () => import('@/views/payView.vue'),
                        path: "/pay",
                        name: "门诊缴费记录",
                        children: [
                            {
                                id: 13,
                                pid: 3,
                                redirect: null,
                                component: () => import('@/views/payDetailView.vue'),
                                path: "/pay/detail",
                                name: "具体缴费明细"
                            }
                        ]
                    },
                    {
                        id: 4,
                        pid: 2,
                        redirect: null,
                        component: () => import('@/views/reservationView.vue'),
                        path: "/reservation",
                        name: "预约记录"
                    }
                ]
            },
            {
                id: 8,
                pid: 0,
                path: '/hospital',
                name: '住院',
                component: () => import('@/views/hospitalParentView.vue'), // 添加父级组件
                children: [
                    {
                        id: 9,
                        pid: 8,
                        redirect: null,
                        component: () => import('@/views/hospitalView.vue'),
                        path: "/hospitalpay",
                        name: "住院缴费记录"
                    },
                    {
                        id: 10,
                        pid: 8,
                        redirect: null,
                        component: () => import('@/views/roomView.vue'),
                        path: "/room",
                        name: "房间管理"
                    },
                    {
                        id: 11,
                        pid: 8,
                        redirect: null,
                        component: () => import('@/views/inpatientView.vue'),
                        path: "/inpatient",
                        name: "住院人"
                    }
                ]
            }
        ]
    }
];

3.这个数组是模拟接口返回的数据(不包含component)

复制代码
// 动态路由配置(权限过滤后的结构)
const dynamicRouteConfigs = [
    {
        path: '/home',
        name: '首页',
        id: 1,
        pid: 0
    },

    {
        id: 2,
        pid: 0,
        redirect: null,
        path: '/comp',
        name: '门诊',
        children: [
            {
                id: 3,
                pid: 2,
                redirect: null,
                path: "/pay",
                name: "门诊缴费记录",
                children: [
                    {
                        id: 13,
                        pid: 3,
                        redirect: null,
                        path: "/pay/detail",
                        name: "具体缴费明细"
                    }
                ]
            },
            {
                id: 4,
                pid: 2,
                redirect: null,
                path: "/reservation",
                name: "预约记录"
            }
        ]
    },
    {
        id: 8,
        pid: 0,
        path: '/hospital',
        name: '住院',
        children: [
            {
                id: 9,
                pid: 8,
                redirect: null,
                path: "/hospitalpay",
                name: "住院缴费记录"
            },
            {
                id: 10,
                pid: 8,
                redirect: null,
                path: "/room",
                name: "房间管理"
            },
            {
                id: 11,
                pid: 8,
                redirect: null,
                path: "/inpatient",
                name: "住院人"
            }
        ]
    }, {
        path: '/message',
        name: '住院人信息',
        id: 12,
        pid: 0
    },
];

注册静态路由

复制代码
// 创建路由实例,只注册静态路由
const router = createRouter({
    history: createWebHistory(),
    routes: baseRoutesWithoutComponents
});

数据处理

复制代码
// 改进的权限过滤方法,支持多维数组(嵌套路由)
const filterRoutes = (dynamicRouteConfigs, allRoutes) => {
    // 递归查找匹配的路由
    const findMatchedRoute = (routes, target) => {
        for (const route of routes) {
            // 匹配条件:name和path都相同
            if (route.name === target.name && route.path === target.path) {
                return route;
            }
            // 如果有子路由,递归查找
            if (route.children) {
                const matchedChild = findMatchedRoute(route.children, target);
                if (matchedChild) return matchedChild;
            }
        }
        return null;
    };

    // 递归处理路由配置
    const processRoutes = (routes) => {
        return routes.map(route => {
            // 查找匹配的路由配置
            const matchedRoute = findMatchedRoute(allRoutes, route);

            if (!matchedRoute) return null;

            // 创建新的路由配置
            const newRoute = {
                ...route,
                component: matchedRoute.component,
                redirect: matchedRoute.redirect || null
            };

            // 递归处理子路由
            if (route.children && route.children.length > 0) {
                newRoute.children = processRoutes(route.children);
            }

            return newRoute;
        }).filter(route => route !== null);
    };

    return processRoutes(dynamicRouteConfigs);
};

将处理后的数据添加到静态路由

复制代码
// 动态添加路由到 layout
const addDynamicRoutes = (roles) => {
    // 清空已有动态路由
    const layout = router.getRoutes().find(r => r.name === 'layout');
    if (layout) {
        layout.children.forEach(child => {
            router.removeRoute(child.name);
        });
    }

    // 过滤并添加新路由
    const allowedRoutes = filterRoutes(dynamicRouteConfigs, baseRoutesWithComponents);
    allowedRoutes.forEach(route => {
        router.addRoute('layout', route);
    });

    // 存储路由信息
    sessionStorage.setItem('menuPath', JSON.stringify(allowedRoutes));
    sessionStorage.setItem('menuName', JSON.stringify(router.getRoutes()));

    // 确保 404 最后处理
    router.addRoute({
        path: '/:pathMatch(.*)*',
        redirect: '/404'
    });

    console.log('动态路由添加完成:', allowedRoutes);
};

// 示例调用(实际使用时应该根据用户权限调用)
addDynamicRoutes();
相关推荐
1024小神2 分钟前
突然原本git链接仓库失败问题排查,竟然是少了.git
前端·javascript
Emma歌小白4 分钟前
Vite 和 Vue CLI 比较
vue.js·vite
不爱说话郭德纲11 分钟前
产品:上传图片拖拽一下怎么了 ?
前端·javascript·vue.js
make16 分钟前
AI 流式请求工具函数 (通义千问)
前端·javascript
作曲家种太阳18 分钟前
加餐-Vue3的渲染系统流程解说【手摸手带你实现一个vue3】
前端
前端太佬23 分钟前
前端对接微信扫码登录:从踩坑到填坑的全记录
前端·javascript·微信
京东零售技术32 分钟前
Taro on Harmony :助力业务高效开发纯血鸿蒙应用
前端·开源
前端大白话1 小时前
救命!这10个Vue3技巧藏太深了!性能翻倍+摸鱼神器全揭秘
前端·javascript·vue.js
嘻嘻嘻嘻嘻嘻ys1 小时前
《Vue 3全栈架构实战:Vite工程化、Pinia状态管理与Nuxt 3深度解析》
前端·后端
前端大白话1 小时前
前端人必看!10个JavaScript“救命”技巧,让你告别加班改Bug
前端·javascript·程序员