前言
Vue 项目的动态路由大体可分为两种:
-
前端方面将路由都规定好,登录时根据用户角色权限来动态展示路由;
-
后端处理对应的数据,通过请求接口来获取当前用户对应权限的路由表。
本文所讲的是最近项目用到的,第二种方式,主要是利用 Vue Router
的一些相关功能实现后端主导的动态路由。
Vue Router 相关了解
全局前置守卫
,可以使用 router.beforeEach
注册一个全局前置守卫:
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
当触发导航时,全局前置守卫按照创建顺序调用。
利用全局前置守卫的特性,在触发导航页面加载前,将当前用户所用到的路由表通过 router.addRoutes
方法添加到 Router 实例中。
具体实现
- 根据和后端商定的数据格式封装一个处理返回的路由表的方法
import Layout from '@/layout'
export function generateRouteList(list) {
const result = []
list.map(item => {
const obj = {
path: item.url,
meta: { title: item.display_name },
name: item.name,
hidden: !!item.hidden
}
if (item.component === 'Layout') {
obj.component = Layout
} else {
const str = item.component && item.component.replace('@/views', '')
obj.component = resolve => require([`../views${str}`], resolve)
}
if (item.child.length !== 0) {
obj.children = generateRouteList(item.child)
}
result.push(obj)
})
return result
}
-
判断用户是否登录。
如未登录,跳转登录页面;
若已登录,判断是否已获取路由列表,已获取则跳转对应路由页面,如未获取则请求接口获取并保存至
vuex
中
if('登录'){
if (!store.getters.routeList.length) { // 判断是否已获取路由列表
await store.dispatch('user/getMenu')
router.matcher = createRouter(constantRoutes).matcher
router.addRoutes(store.getters.routeList)
next({ ...to, replace: true })
}
next()
} else {
'去登录'
}
常见问题
动态路由配合路由懒加载
-
使用 import() 的话,不能传入变量,不然编译时能确定从哪里找到文件模块
可以使用模板字符串的方法,但在本项目中因为项目配置的 eslint 的一些规则,无法使用import 结合模板字符串的方法,最终通过查阅,采用了 require 实现懒加载的方法,使用 require 时在拼接路径时也必须把基本路径确定下来,因为需要提供部分信息 webpack 才能编译。
-
动态路由刷新后404
其原因是在拼接基本静态路由和动态生成路由时,没有将404页面的匹配规则放置在路由表最后。