vue-router 4.0 取消了 addRouters 设置动态路由只能使用 addRouter
动态路由一般是从后端获取 然后经过数据格式处理
但在页面刷新后会出现一下警告:
vue-router.esm-bundler.js?6c02:71 [Vue Router warn]: No match found for location with path “/formlist/stepform/other”
但通过getRouters
又能够获取到所有的异步路由
分析:页面刷新后由于是异步获取的原因 在next() 函数放行之后才获取到
此时就要使用next({ ...to, replace: true })
来确保addRoute()
时动态添加的路由已经被完全加载上去。
next({ ...to, replace: true })
中的replace: true
只是一个设置信息,告诉VUE本次操作后,不能通过浏览器后退按钮,返回前一个路由。
因此next({ ...to, replace: true })
可以写成next({ ...to })
,不过你应该不希望用户在addRoute()
还没有完成的时候,可以点击浏览器回退按钮搞事情吧。
其实next({ ...to })
的执行很简单,它会判断:
如果参数to不能找到对应的路由的话,就再执行一次beforeEach((to, from, next))
直到其中的next({ ...to})
能找到对应的路由为止。
也就是说此时addRoute()
已经完成啦,找到对应的路由之后,接下来将执行前往对应路由的beforeEach((to, from, next)
,因此需要用代码来判断这一次是否就是前往对应路由的beforeEach((to, from, next),
如果是,就执行next()放行。
如果守卫中没有正确的放行出口的话,会一直next({ ...to})
进入死循环 !!!
因此你还需要确保在当addRoute()
已经完成时,所执行到的这一次beforeEach((to, from, next))
中有一个正确的next()
方向出口。
解决:
router.beforeEach(async (to, from, next) => {
NProgress.start()
to.meta && (typeof to.meta.title !== 'undefined' && setDocumentTitle(`${domTitle}-${to.meta.title}`))
//判断是否登录
if (VueCookies.get(ACCESS_TOKEN)) {
if (to.path == '/loginview/login') {
next({ path: '/form/formlist' })
} else {
// 一定要有一个执行条件 否则会进入死循环
if (store.state.permission.addRouters.length == 0) {
await store.dispatch('GenerateRoutes').then((res) => {
const asyncRouter = res
asyncRouter.forEach(v => {
router.addRoute(v)
})
// 如果 addRoute 并未完成,路由守卫会一层一层的执行执行,直到 addRoute 完成,找到对应的路由
next({ ...to, replace: true })
})
} else {
next()
}
}
} else {
//免登录菜单
if (whiteList.includes(to.name)) {
next()
} else {
next({ path: '/loginview/login', query: { redirect: to.fullPath } })
}
}
})
在router.config.js 基础路由里面加上 404页面(防止浏览器刷新时路由未找到警告提示)
import { BasicLayouts, LoginView, RouteView } from '@/layouts'
/**
* 基础路由
* @type { *[] }
*/
export const routerMap = [
{
path: '/loginview',
component: LoginView,
redirect: '/loginview/login',
children: [
{
path: '/loginview/login',
name: 'login',
component: () => import('@/views/Login/Login'),
meta: { title: '登录' }
},
]
},
{
path: '/',
component: BasicLayouts,
redirect: '/home',
children: [
{
path: '/home',
name: 'Home',
component: () => import('@/views/home/home'),
meta: { title: '首页' }
},
]
},
{
hide: true,
path: '/:pathMatch(.*)*',
component: () => import('@/views/Exception/404'),
},
]
完整代码地址可参考 gtee:https://gitee.com/ZHANG_6666/crm-template/tree/develop/
完全与服务端交互:https://gitee.com/ZHANG_6666/crm-template
服务端:https://gitee.com/ZHANG_6666/express–vue3–ant-design2