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();
相关推荐
花楸树10 分钟前
前端搭建 MCP Client(Web版)+ Server + Agent 实践
前端·人工智能
wuaro10 分钟前
RBAC权限控制具体实现
前端·javascript·vue
专业抄代码选手15 分钟前
【JS】instanceof 和 typeof 的使用
前端·javascript·面试
用户00798136209716 分钟前
6000 字+6 个案例:写给普通人的 MCP 入门指南
前端
用户876128290737420 分钟前
前端ai对话框架semi-design-vue
前端·人工智能
干就完了123 分钟前
项目中遇到浏览器跨域前端和后端解决方案以及大概过程
前端
我是福福大王25 分钟前
前后端SM2加密交互问题解析与解决方案
前端·后端
实习生小黄28 分钟前
echarts 实现环形渐变
前端·echarts
_未知_开摆36 分钟前
uniapp APP端在线升级(简版)
开发语言·前端·javascript·vue.js·uni-app
喝拿铁写前端1 小时前
不同命名风格在 Vue 中后台项目中的使用分析
javascript·vue.js