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();
相关推荐
Joker`s smile2 分钟前
使用React+ant Table 实现 表格无限循环滚动播放
前端·javascript·react.js
国家不保护废物7 分钟前
🌟 React 魔法学院入学指南:从零构建你的第一个魔法阵(项目)!
前端·react.js·架构
然我8 分钟前
从原生 JS 到 React:手把手带你开启 React 业务开发之旅
javascript·react.js·前端框架
import_random10 分钟前
[机器学习]svm支持向量机(优势在哪里)
前端
国家不保护废物11 分钟前
从刀耕火种到现代框架:DOM编程 vs Vue/React 进化史
前端·vue.js·react.js
陈随易11 分钟前
Univer v0.8.0 发布,开源免费版 Google Sheets
前端·后端·程序员
wkj00116 分钟前
QuaggaJS 配置参数详解
java·linux·服务器·javascript·quaggajs
不怎么爱学习的dan17 分钟前
实现 ECharts 多国地区可视化方案
前端
嘉小华17 分钟前
Android Lifecycle 状态同步与分发机制深度解析
前端
李三岁_foucsli23 分钟前
chrome架构-多进程和进程中的线程
前端·google