回顾一下将Ant Design Vue Pro静态路由改为动态路由。由于业务需求,需要对Ant Design Vue Pro框架的路由部分进行一个重构,
首先Ant Design Vue Pro是带有两套路由的,分别需要在不同的地方进行配置,下面就来说说我开发过程中碰到的问题并如何解决的
src\store\index.js
src\store\modules\async-router.js
src\store\modules\user.js
src\router\index.js
src\router\generator-routers.js
首先我们需要找到src\store\index.js文件
把import permission from ‘./modules/static-router’ 注释掉 这个是静态路由
把import permission from ‘./modules/async-router’ 放开 这个是表示引用的动态路由
找到 GetInfo方法 这个方法是获取用户信息的 直接去src\api\login.js文件中修改请求路径 其中写的时候要看看后端传过来的数据结构,根据自己后端传过来的结构进行调整
第三步 找到src\store\modules\async-router.js 找到generatorDynamicRouter方法进去src\router\generator-routers.js里面
要注意的是这边后端的数据结构与你自己请求后端传过来的数据结构是否一样 现在的是
//官方传过来的数据结构
{
name: 'dashboard',
parentId: 0,
id: 1,
meta: {
title: 'menu.dashboard',
icon: 'dashboard',
show: true
},
component: 'RouteView',
redirect: '/dashboard/workplace'
}
// form
{
name: 'form',
parentId: 0,
id: 10,
meta: {
icon: 'form',
title: 'menu.form'
},
redirect: '/form/base-form',
component: 'RouteView'
},
{
name: 'basic-form',
parentId: 10,
id: 6,
meta: {
title: 'menu.form.basic-form'
},
component: 'BasicForm'
},
然后我这边后端传过来的数据结构是 后端这边把数据结构给我处理好了 我只需要对部分字段键值进行修改就好了 方法也可以给你们参考一下 这边的改动也是最复杂的
// 我这边后端传过来的数据结构
[
{name:'数据总览',
id:'1',
component:"RouteView",
parentId: 0,
url: "/dashboard",
children:[{children:'',parentId:'1',title:'数据分表',url:'/dashboard/supplyHome'}]
},
{name:'数据总览',
id:'1',
component:"RouteView",
parentId: 0,
url: "/dashboard",
children:[{children:'',parentId:'1',title:'数据分表',url:'/dashboard/supplyHome'}]
},
]
// 解构拆分方法
/**
* 动态生成菜单
* @param token
* @returns {Promise}
*/
export const generatorDynamicRouter = () => {
return new Promise((resolve, reject) => {
const pores = storage.get('self_list')
loginService.getCurrentUserNav().then(res => {
console.log(res.data)
if (res.code === 200){
const list = JSON.stringify(res.data).replace(/childMenu/g, "children")
const result = JSON.parse(list)
console.log(result)
const menuNav = []
const childrenNav = []
// 后端数据, 根级树数组, 根级 PID
// listToTree(result, childrenNav, 0)
rootRouter.children = result
rootRouter.children.forEach(item=>{
item.component = 'RouteView'
item.title = item.name
item.children.forEach(o=>{
if (o.url.split('/').length>2){
o.component = o.url.split('/')[o.url.split('/').length-2]+capitalized(o.url.split('/')[o.url.split('/').length-1])
o.title = o.name
o.name = o.url.split('/')[o.url.split('/').length-2]+capitalized(o.url.split('/')[o.url.split('/').length-1])
}
})
})
menuNav.push(rootRouter)
const routers = generator(menuNav)
// routers.push(notFoundRouter)
routers[0].redirect = '/dashboard'
routers[0].meta.title = '首页'
routers[0].name = 'index'
resolve(routers)
}
})
})
}
/**
* 格式化树形结构数据 生成 vue-router 层级路由表
* @param routerMap
* @param parent
* @returns {*}
*/
export const generator = (routerMap, parent) => {
return routerMap.map( item => {
// const { title, show, hideChildren, hiddenHeaderContent, target, icon } = item.meta || {}
// const currentRouter = item
const currentRouter = {
// 如果路由设置了 path,则作为默认 path,否则 路由地址 动态拼接生成如 /dashboard/workplace
path: item.url || `${(parent && parent.url) || ''}/${item.key}`,
// 路由名称,建议唯一
key: item.url,
name: item.name || item.key || '',
// 该路由对应页面的 组件 :方案1
component: constantRouterComponents[item.component],
// 该路由对应页面的 组件 :方案2 (动态加载)
// component: constantRouterComponents[item.component || item.key] || (() => import(`@/views/${item.component}`)),
// meta: 页面标题, 菜单图标, 页面权限(供指令权限用,可去掉)
meta: {
title: item.title,
icon: item.icon || undefined,
// hiddenHeaderContent: hiddenHeaderContent,
// target: target,
permission: item.permission
}
}
// if (item.type === 0) {
// currentRouter.component = RouteView
// }else if (item.type !== 0){
// currentRouter.component = constantRouterComponents[item.url]
// }
// // 是否设置了隐藏菜单
// if (show === false) {
// currentRouter.hidden = true
// }
// // 是否设置了隐藏子菜单
// if (hideChildren) {
// currentRouter.hideChildrenInMenu = true
// }
// 为了防止出现后端返回结果不规范,处理有可能出现拼接出两个 反斜杠
if (!currentRouter.path.startsWith('http')) {
currentRouter.path = currentRouter.path.replace('//', '/')
}
// 重定向
// item.url && (currentRouter.path = item.url)
// 是否有子菜单,并递归处理
if (item.children && item.children.length > 0) {
// Recursion
currentRouter.children = generator(item.children, currentRouter)
}
return currentRouter
})
}
// 字符换第一个字母大写
const capitalized = (name)=>{
const capitalizedFirst = name[0].toUpperCase();
const rest = name.slice(1);
return capitalizedFirst + rest;
}
然后还要再\src\store\modules\async-router.js 文件中修改一下逻辑
actions: {
GenerateRoutes ({ commit }, data) {
return new Promise(resolve => {
generatorDynamicRouter().then(routers => {
routers[0].children.forEach(item=>{
item.redirect = item.children[0].path
item.name = item.path.split('/')[1]
delete item.key
item.children.forEach(list=>{
list.meta.title = list.meta.title.split('-')[0]
})
asyncRouterMap[0].children.forEach(op=>{
if (op.path == item.path) {
op.redirect = item.redirect
item.children.concat(op.children)
}
})
})
commit('SET_ROUTERS', routers)
resolve()
})
})
}
经过这些处理之后后端传过来的数据结构就变成了
[{
path: '/',
name: 'index',
component: BasicLayout,
meta: { title: 'menu.home' },
redirect: '/dashboard/workplace',
children:[
{
path: '/dashboard',
name: 'dashboard',
redirect: '/dashboard/workplace',
component: RouteView,
meta: { title: 'menu.dashboard', keepAlive: true, icon: bxAnaalyse, permission: ['dashboard'] },
children: [
{
path: '/dashboard/analysis/:pageNo([1-9]\\d*)?',
name: 'Analysis',
component: () => import('@/views/dashboard/Analysis'),
meta: { title: 'menu.dashboard.analysis', keepAlive: false, permission: ['dashboard'] }
},
// forms
{
path: '/form',
redirect: '/form/base-form',
component: RouteView,
meta: { title: 'menu.form', icon: 'form', permission: ['form'] },
children: [
{
path: '/form/base-form',
name: 'BaseForm',
component: () => import('@/views/form/basicForm'),
meta: { title: 'menu.form.basic-form', keepAlive: true, permission: ['form'] }
},
{
path: '/form/step-form',
name: 'StepForm',
component: () => import('@/views/form/stepForm/StepForm'),
meta: { title: 'menu.form.step-form', keepAlive: true, permission: ['form'] }
},
{
path: '/form/advanced-form',
name: 'AdvanceForm',
component: () => import('@/views/form/advancedForm/AdvancedForm'),
meta: { title: 'menu.form.advanced-form', keepAlive: true, permission: ['form'] }
}
]
},
]
}]
到这里动态路由改造的就完成了,其中要注意两点
1.启动首页有可能会出现白屏现象,解决办法可以参考 Ant Design Vue Pro 动态路由加载,服务器重启首页白屏
2.要注意SET_ROLES的配置 这里没配置好的话会一直进入死循环,造成内存溢出