1 | router.addRoutes(routes: Array<RouteConfig>) |
说得比较简单,假设c是从后台获取到的权限路由,那么:
1 | [{path='a'},{path='b'}].addRoutes([{path='c'}]) = [{path='a'},{path='b'},{path='c'}] |
可以看出只能往后追加,如果我要c作为a的子路由,变成这样
1 | [{path='a',children:[{path='c'}]},{path='b'} |
addRoutes方法不能在已存在的路由下添加子路由,具体讨论请看:https://github.com/vuejs/vue-router/issues/1156
下面记录一下我的开发过程:
页面结构为一个大的home页,里面有sysa、sysb、sysc等很多模块,点击任何一个模块都会跳login页,登录一个模块后其他模块也就登录了,所以采用了子路由的方式
1 | // router/index.js 主路由 |
- 思路1:我把adminRoutes外面包一层,变成sysaRoutes的形式,然后用addRoutes方法,它会直接覆盖addRoutes,失败
- 思路2:如果有一个方法addRoutes([parentName, ]routes),可以指定父级,那么就简单了,可惜没有这样的方法。找到一个类似的 EnhancedRouter.js,经过测试并不好用,当adminRoutes还有子路由的时候报重复路由,本身是for遍历,对性能太差了,失败
- 思路3:我获取到原路由,做判断,当r.path===’/sysa’的时候,把adminRoutes加到children里去
1
2
3
4
5
6// permission.js 拦截器里
const accessRoutes = await store.dispatch('permission/generateRoutes', authorities)
const { routes } = router.options
const indexRoutes = routes.find(r => r.path === '/sysa')
indexRoutes.children.push.apply(indexRoutes.children, accessRoutes)
router.addRoutes([indexRoutes])
这样结构虽然对了,但是破坏了原有observer,所以点击’/sysa/stat2’都是空白页,失败
- 思路4:既然addRoutes不能添加到子路由,那么我在生成权限路由的时候干脆直接生成sysa,去掉主路由里的sysaRoutes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43// store/modules/permission.js
import { constantRoutes } from '@/router'
// 去掉主路由里的sysaRoutes,放到了这里
import sysaRoutes from '@/views/sysa/routes'
import zbxSupportRoutes from '@/router/roles/zbxSupportRoutes'
const state = {
routes: [],
addRoutes: []
}
const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
}
}
const actions = {
generateRoutes({ commit }, roles) {
return new Promise(resolve => {
let accessedRoutes
if (roles.includes('ROLE_zbxSupport')) {
sysaRoutes.children.push.apply(sysaRoutes.children, zbxSupportRoutes)
// 模块路由+权限路由
accessedRoutes = sysaRoutes
} else {
// ...
}
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
// permission.js 拦截器里
const accessRoutes = await store.dispatch('permission/generateRoutes', authorities)
// 这回这里accessRoutes可是一个完整的{}路由
router.addRoutes([accessRoutes])
终于成功了
最后侧边要显示模块sysa菜单
1 | computed: { |
总结,一开始总想着要追加到子路由,舍不得把模块路由去掉,忽略了发挥addRoutes的能力