接口返回数据整理成动态路由
后端接口返回数据
{
"code": 20000,
"value": [
{
"path": "/example",
"component": "layout/index.vue",
"redirect": "/example/table",
"name": "Example",
"meta": { "title": "Example", "icon": "el-icon-s-help" },
"children": [
{
"path": "table",
"name": "Table",
"component": "views/table/index.vue",
"meta": { "title": "Table", "icon": "table" }
},
{
"path": "tree",
"name": "Tree",
"component": "views/tree/index.vue",
"meta": { "title": "Tree", "icon": "tree" }
}
]
}
]
}
整理数据
1.不用import的原因是webpack4X,import不能使用变量(有时候多几层字符串拼接也可以eg: '@/views/
x
x
x
.
v
u
e
′
),所以这里使用
(
r
e
s
o
l
v
e
)
=
>
r
e
q
u
i
r
e
(
[
‘
@
/
{xxx}.vue'),所以这里使用(resolve) => require([`@/
xxx.vue′),所以这里使用(resolve)=>require([‘@/{component}`], resolve) 处理接口返回的component
2.require和import区别
-
语法:
-使用(resolve) => require([@/views/${view}], resolve)是使用require语法来动态加载组件,而import ( )是ES6的模块导入语法。 -
动态加载:
-(resolve) => require([@/views/${view}], resolve)可以在运行时动态加载组件,而import ( )只能在编译时静态导入组件。 -
异步加载:
-(resolve) => require([@/views/${view}], resolve)可以实现异步加载组件,只有在需要时才会加载对应的组件文件:只有访问这个路由网址时才会加载这个js。而import ( )会在编译时将所有导入的组件一起打包,无法实现异步加载,当项目打包时路由里的所有component都会打包在一个js 中,造成进入首页时,需要加载的内容过多,时间相对比较长 -
代码分割:
-(resolve) => require([@/views/${view}], resolve)可以实现代码分割,将不同的组件打包成不同的文件,按需加载。而import ( )会将所有导入的组件打包到一个文件中。你可以打包的时候看看目录结构就明白了。
综上所述:使用(resolve) => require([@/views/${view}], resolve)拼接component可以实现动态、异步加载和代码分割等功能,适用于需要按需加载和优化性能的场景。而import ( )适用于静态导入和编译时打包的场景。
function loadView(component) {
return (resolve) => require([`@/${component}`], resolve)
}
// 处理动态路由
export function formatRoutes(menu) {
const router = []
menu.forEach(menuItem => {
if (!validateNull(menuItem.component)) {
const routerItem = {
...menuItem,
component: loadView(menuItem.component),
children: validateNull(menuItem.children) ? [] : formatRoutes(menuItem.children),
}
router.push(routerItem)
}
})
return router
}
想要左侧菜单使用router.addRoutes()之后的全部路由,发现如下问题
- 当router.addRoutes()之后打印router.options.routes打印出来的并不是全量的路由,仍然只有基本路由(虽然打印不出来,但是不影响使用,页面跳转没有任何问题)----只给matcher对象增加了新路由,并没有更新router.option,matcher对象是给vue-router内部使用的,所以项目里页面跳转没有出问题,但router.option打印不出来
- 调用getRoutes报错----3.5.4版本的源码,发现vue官方新增了getRoutes方法,用于获取matcher对象上的全量路由
解决方案: 使用状态管理工具,自行保存一份路由数据
store/modules/menu.js
import { constantRoutes, lastRoutes } from '@/router'
import { getMenu } from '@/api/systemManage'
const state = {
menu: constantRoutes
}
const mutations = {
SET_MENU: (state, dynamicMenu) => {
state.menu = constantRoutes.concat(dynamicMenu, lastRoutes)
}
}
const actions = {
// get menu
GetMenu({ commit, state }) {
return new Promise((resolve, reject) => {
getMenu().then(res => {
const dynamicMenu = res.value || []
commit('SET_MENU', dynamicMenu)
resolve(dynamicMenu)
}).catch(error => {
reject(error)
})
})
}
}
export default {
namespaced: true, // 模块的上下文局部化,使其成为带命名空间的模块,模块的 getter、action 和 mutation 会带上模块的路径作为前缀,使用时需要指定完整路径。
state,
mutations,
actions
}