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();
相关推荐
特立独行的猫a6 分钟前
DeepSeek Harness插件和工具的区别介绍及开发入门指南
前端·ai·agent·插件·deepseek·harness
小新讲网安11 分钟前
HTTP请求走私攻击实战:CL.TE与TE.CL绕过前端服务器全解析
服务器·前端·网络·web安全·http·架构·漏洞
风骏时光牛马15 分钟前
AI办公系统异常事件复盘分析
前端
console.log('npc')18 分钟前
React 19 + Vite 企业级前端项目:从零搭建到规范交付
前端·react.js·前端框架
程序员黑豆24 分钟前
Java字符串常量池完全指南:原理、intern()方法与性能优化最佳实践
java·前端·ai编程
光影少年24 分钟前
react离线缓存、图片缓存方案
开发语言·前端·javascript·react native·react.js·缓存·前端框架
Canace30 分钟前
笔记本都合上了,Claude 为什么还能在手机上执行电脑上装的技能?
前端·人工智能·ai编程
cyadyx2 小时前
Vite 比 Webpack 构建效率更高
前端·webpack·node.js·vite
mCell3 小时前
AI 时代 SVG 画图的潜力
前端·agent·svg
我命由我123459 小时前
CesiumJS 笔记 - 获取容器中心点、Cartesian3 clone 方法、修改 Cartesian3 对象的高度
前端·javascript·css·前端框架·html·html5·js