Vue实现动态路由
动态路由设置一般有两种一、简单的角色路由设置前端控制这种方式适用于角色较少且权限相对固定的场景。前端预先定义好所有可能的路由和对应的角色权限然后根据用户登录时获取的角色信息来筛选出用户可访问的路由。代码实现1、路由配置文件 (router/index.js)定义静态路由和异步路由权限路由。import Vue from vue import VueRouter from vue-router import Layout from /layout import store from /store // 假设使用 Vuex 存储用户角色 Vue.use(VueRouter) // 静态路由无需权限即可访问 export const constantRoutes [ { path: /login, component: () import(/views/login), hidden: true }, { path: /404, component: () import(/views/404), hidden: true } ] // 异步路由根据角色权限加载 export const asyncRoutes [ { path: /permission, component: Layout, redirect: /permission/page, alwaysShow: true, name: Permission, meta: { title: 权限管理, roles: [admin, editor] // 普通的用户角色 }, children: [ { path: page, component: () import(/views/permission/page), name: PagePermission, meta: { title: 页面权限, roles: [editor] // editor角色的用户才能访问该页面 } }, { path: role, component: () import(/views/permission/role), name: RolePermission, meta: { title: 角色权限, roles: [admin] // admin角色的用户才能访问该页面 } } ] }, { path: /dashboard, component: Layout, name: Dashboard, meta: { title: 仪表盘, roles: [admin, user] // admin 和 user 都可以访问 } } // 可以继续添加更多异步路由... ] const createRouter () new VueRouter({ mode: history, scrollBehavior: () ({ y: 0 }), routes: constantRoutes }) const router createRouter() // 用于重置路由的方法例如用户登出后 export function resetRouter() { const newRouter createRouter() router.matcher newRouter.matcher // 重置路由匹配器 } export default router2、权限过滤工具 (utils/asyncRouter.js)根据用户角色过滤异步路由。/** * 判断当前用户是否有访问该路由的权限 * param {Array} roles - 用户的角色列表 * param {Object} route - 路由对象 * returns {Boolean} */ export function hasPermission(roles, route) { if (route.meta route.meta.roles) { // 如果路由定义了需要的角色则检查用户角色是否包含在内 return roles.some(role route.meta.roles.includes(role)) } else { // 如果没有定义角色则默认允许访问 return true } } /** * 递归过滤异步路由表筛选出用户有权限访问的路由 * param {Array} routes - 异步路由列表 * param {Array} roles - 用户的角色列表 * returns {Array} */ export function filterAsyncRoutes(routes, roles) { const res [] routes.forEach(route { const tmp { ...route } if (hasPermission(roles, tmp)) { // 如果有子路由递归过滤子路由 if (tmp.children) { tmp.children filterAsyncRoutes(tmp.children, roles) } res.push(tmp) } }) return res }3、路由守卫 (permission.js)在路由跳转前进行权限判断。import router from ./router import store from ./store import { getToken } from /utils/auth // 假设有一个获取 token 的工具函数 import { filterAsyncRoutes } from /utils/asyncRouter // 引入权限过滤工具 import NProgress from nprogress // 进度条 import nprogress/nprogress.css NProgress.configure({ showSpinner: false }) const whiteList [/login] // 白名单不需要登录即可访问的路由 router.beforeEach(async (to, from, next) { // 开始进度条 NProgress.start() // 获取 token const token getToken() if (token) { // 如果已经登录 if (to.path /login) { // 如果访问的是登录页则跳转到首页 next({ path: / }) NProgress.done() } else { // 检查用户信息是否已获取 const hasRoles store.getters.roles store.getters.roles.length 0 if (hasRoles) { // 如果用户角色已存在则直接进入 next() } else { try { // 获取用户信息通常包含角色 const { roles } await store.dispatch(user/getUserInfo) // 根据用户角色过滤路由 const accessRoutes filterAsyncRoutes(asyncRoutes, roles) // 动态添加路由 router.addRoutes(accessRoutes) // 将过滤后的路由存入 store可选用于菜单渲染等 store.commit(permission/SET_ROUTES, accessRoutes) // 继续导航 next({ ...to, replace: true }) } catch (error) { // 获取用户信息失败清除 token 并跳转到登录页 await store.dispatch(user/resetToken) next(/login?redirect${to.path}) NProgress.done() } } } } else { // 如果未登录 if (whiteList.indexOf(to.path) ! -1) { // 如果是白名单中的路由则直接进入 next() } else { // 否则跳转到登录页 next(/login?redirect${to.path}) NProgress.done() } } }) // 路由结束 router.afterEach(() { NProgress.done() })二、复杂的路由权限设置后端控制这种方式适用于权限复杂、角色多变的系统。前端不预先定义所有路由而是由后端返回用户当前拥有的路由列表前端根据这个列表动态添加路由。代码实现1、路由配置文件 (router/index.js)只定义静态路由和一个空的动态路由数组import Vue from vue import VueRouter from vue-router import Layout from /layout import store from /store Vue.use(VueRouter) // 静态路由无需权限即可访问 export const constantRoutes [ { path: /login, component: () import(/views/login), hidden: true }, { path: /404, component: () import(/views/404), hidden: true } ] // 动态路由由后端返回 export const asyncRoutes [] const createRouter () new VueRouter({ mode: history, scrollBehavior: () ({ y: 0 }), routes: constantRoutes }) const router createRouter() export function resetRouter() { const newRouter createRouter() router.matcher newRouter.matcher } export default router2、API 请求工具 (api/user.js)用于获取用户权限路由列表。import request from /utils/request // 获取用户信息包含角色 export function getUserInfo() { return request({ url: /user/info, method: get }) } // 获取用户权限路由列表后端返回 export function getPermissionRoutes() { return request({ url: /user/permission/routes, method: get }) }3、路由守卫 (permission.js)在用户登录后调用后端接口获取路由列表并动态添加。import router from ./router import store from ./store import { getToken } from /utils/auth import { getPermissionRoutes } from /api/user // 引入获取权限路由的 API import NProgress from nprogress import nprogress/nprogress.css NProgress.configure({ showSpinner: false }) const whiteList [/login] router.beforeEach(async (to, from, next) { NProgress.start() const token getToken() if (token) { if (to.path /login) { next({ path: / }) NProgress.done() } else { const hasRoles store.getters.roles store.getters.roles.length 0 if (hasRoles) { next() } else { try { // 获取用户信息通常包含角色 const { roles } await store.dispatch(user/getUserInfo) // 获取后端返回的权限路由列表 const routeData await getPermissionRoutes() // 假设后端返回的路由数据结构是 { routes: [...], ... } const accessRoutes routeData.routes || [] // 动态添加路由 router.addRoutes(accessRoutes) // 将过滤后的路由存入 store可选用于菜单渲染等 store.commit(permission/SET_ROUTES, accessRoutes) next({ ...to, replace: true }) } catch (error) { await store.dispatch(user/resetToken) next(/login?redirect${to.path}) NProgress.done() } } } } else { if (whiteList.indexOf(to.path) ! -1) { next() } else { next(/login?redirect${to.path}) NProgress.done() } } }) router.afterEach(() { NProgress.done() })总结说明一 (前端控制)通过在路由配置中定义 meta.roles 字段来标记路由所需的角色。在路由守卫中根据用户角色调用 filterAsyncRoutes 函数过滤出用户可访问的路由并使用 router.addRoutes 动态添加。这种方式简单直接适合权限结构相对固定的场景。二 (后端控制)前端不预先定义路由而是通过调用后端 API 获取用户权限对应的路由列表。后端根据用户角色和权限规则生成路由配置通常包含 path, component, meta 等信息前端接收到后直接使用 router.addRoutes 添加。这种方式更灵活适合权限复杂、需要频繁调整的系统但需要后端配合提供路由数据接口。两种方式的核心都是利用 router.addRoutes (Vue Router 3.x) 或 router.addRoute (Vue Router 4.x) 来动态添加路由并结合路由守卫进行权限判断注意vue是单页面应用程序所以页面一刷新数据部分数据也会跟着丢失所以我们需要将store中的数据存储到本地才能保证路由不丢失