这次老板的需求是 路由通过后端配置好 直接给我一个路由树 生成侧边栏 ,也就是说 现在前端并不需要控制权限了,没了角色的概念,路由完全靠后端给我,给我什么我就生成什么。
这就有点匪夷所思,讲道理这套框架就是根据角色去筛选路由表,然后前端渲染,现在改写了路由逻辑,我是很蒙蔽的。既然需求就这样,废话不多说了,直接开干。
项目就是老一套 基于vue-element-admin panjiachen大神的框架做的
首先我们找到permission路由守卫这里 原项目这个文件是来控制路由前的一些校验
image.png
我们找到vuex里响应异步获取路由表"GenerateRoutes"的方法
image.png
可以看到这里是使用filterAsyncRouter这个方法 根据角色 不断递归筛选路由表
image.png
根据pan大神的思路 我自己改写了一下筛选方法(自己倒腾了好久才发现人家其实有类似方法了) 遍历后台传来的路由字符串,转换为组件对象
可以注意到
route.component = () => import('@/views/documentation/index.vue')
这个我是写死的路径 将后台传来的字符串替换为组件
layout直接导入就OK了
...
import Layout from '@/views/layout/Layout'
...
function filterAsyncRouter(asyncRouterMap) { // 遍历后台传来的路由字符串,转换为组件对象
const accessedRouters = asyncRouterMap.filter(route => {
if (route.component) {
if (route.component === 'Layout') { // Layout组件特殊处理
route.component = Layout
} else {
console.log(route.component)
route.component = () => import('@/views/documentation/index.vue')
}
}
if (route.children && route.children.length) {
route.children = filterAsyncRouter(route.children)
}
return true
})
return accessedRouters
}
以下是我用easy-mock自己模拟的路由树
{
"data": {
"router": [
{
"path": "/documentation",
"component": "Layout",
"redirect": "/documentation/index",
"children": [
{
"path": "index",
"component": "documentation/index",
"name": "Documentation",
"meta": {
"title": "documentation",
"icon": "documentation",
"noCache": true
}
}
]
}
]
}
}
这是后台传来的路由渲染出来的
按理说到现在 已经可以动态挂载路由了吧? 那你就错了 看到我上边组件是写死的路径了吗 实际应用场景我们需要把他替换为一个变量 就像这样:
function filterAsyncRouter(asyncRouterMap) {
const accessedRouters = asyncRouterMap.filter(route => {
if (route.component) {
if (route.component === 'Layout') {
route.component = Layout
} else {
route.component = () => import(`@/views/${route.component}.vue`) // 就像这样 这个变了打印出来就是documentation/index这个字符串
}
}
if (route.children && route.children.length) {
route.children = filterAsyncRouter(route.children)
}
return true
})
return accessedRouters
}
then...
找不到组件?
原因其实是 webpack的现在的实现方式不能实现完全动态。
看看控制台编译后的文件 其实也会被转为一个异步方法
编译后
在查阅了资料(issue...)后 原来如果想要完全使用动态路由 需要把后台传回来的name 和 本地components 做一个映射
//maprouters.js
// 异步取到的路由 router.components的name 和 本地components map 做一个映射
const dynamicRouterMap = {
'documentation/index': () => import(`@/views/documentation/index.vue`),
'nested/menu1/index': () => import(`@/views/nested/menu1/index.vue`),
'nested/menu2/index': () => import(`@/views/nested/menu2/index.vue`)
}
export default { dynamicRouterMap }
// permission.js
...
import DynamicRouterMap from '@/router/maprouters.js'
...
function filterAsyncRouter(asyncRouterMap) { // 遍历后台传来的路由字符串,转换为组件对象
const accessedRouters = asyncRouterMap.filter(route => {
if (route.component) {
if (route.component === 'Layout') { // Layout组件特殊处理
route.component = Layout
} else {
route.component = DynamicRouterMap.dynamicRouterMap[route.component] // 路由映射
}
}
if (route.children && route.children.length) {
route.children = filterAsyncRouter(route.children)
}
return true
})
return accessedRouters
}
OJBK
关于作者
var myproject = {
nickName : "remix_huang",
site : "https://www.jianshu.com/u/717e2ca57b3f"
}
网友评论