vue 实现动态路由
实现动态路由的基本思路
动态路由的核心是根据用户权限或数据动态生成路由表。Vue Router 支持通过 addRoute 方法动态添加路由规则。
定义静态基础路由
静态路由是无需权限即可访问的页面(如登录页、404页等):
const constantRoutes = [
{
path: '/login',
component: () => import('@/views/login.vue')
},
{
path: '/404',
component: () => import('@/views/404.vue')
}
]
获取动态路由数据
通常从后端接口获取用户权限对应的路由配置,数据结构示例:
[
{
"path": "/dashboard",
"component": "Layout",
"children": [
{
"path": "index",
"component": "dashboard/index"
}
]
}
]
路由数据转换
需要将后端返回的组件路径字符串转换为真正的组件:
function loadView(view) {
return () => import(`@/views/${view}.vue`)
}
function filterAsyncRoutes(routes) {
return routes.map(route => {
if (route.component) {
if (route.component === 'Layout') {
route.component = Layout
} else {
route.component = loadView(route.component)
}
}
if (route.children) {
route.children = filterAsyncRoutes(route.children)
}
return route
})
}
动态添加路由
在用户登录后或应用初始化时添加路由:
import router from './router'
const asyncRoutes = filterAsyncRoutes(backendRoutes)
asyncRoutes.forEach(route => {
router.addRoute(route)
})
// 添加404兜底路由(需最后添加)
router.addRoute({ path: '/:pathMatch(.*)', redirect: '/404' })
路由权限控制
结合 Vue Router 的导航守卫实现权限校验:
router.beforeEach((to, from, next) => {
if (hasToken()) {
if (to.path === '/login') {
next('/')
} else {
if (hasRoles()) {
next()
} else {
getRoutes().then(routes => {
// 动态添加路由逻辑
next({ ...to, replace: true })
})
}
}
} else {
if (whiteList.includes(to.path)) {
next()
} else {
next('/login')
}
}
})
菜单生成方案
动态路由通常需要配合动态菜单使用:
function generateMenu(routes) {
return routes.filter(route => {
if (route.meta && route.meta.hidden) return false
if (route.children) {
route.children = generateMenu(route.children)
}
return true
})
}
常见问题处理
路由刷新404问题:需要确保服务器配置支持 History 模式:
location / {
try_files $uri $uri/ /index.html;
}
路由重复添加问题:在添加动态路由前可先重置:

function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher
}
完整示例代码
// permission.js
router.beforeEach(async (to, from, next) => {
if (store.getters.token) {
if (!store.getters.routes.length) {
const { routes } = await store.dispatch('user/getRoutes')
const accessRoutes = await store.dispatch('permission/generateRoutes', routes)
accessRoutes.forEach(route => {
router.addRoute(route)
})
next({ ...to, replace: true })
} else {
next()
}
} else {
next('/login')
}
})
通过以上方案可以实现完整的动态路由系统,包括路由权限控制、菜单动态生成等功能。实际项目中可根据需求调整数据结构和权限校验逻辑。






