vue-router添加动态路由及无限刷新白屏和添加不生效问题_router(1)

本文介绍了如何在Vue.js项目中实现动态路由添加,解决刷新白屏问题,并进行权限管理。通过store状态管理和vue-router的beforeEach钩子函数,根据用户角色动态过滤并添加路由。同时,文章提及了算法在大厂面试中的重要性,并分享了相关学习资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// mutations 是唯一可以更改state的函数,使用SET_ROUTES定义更改方法,SET_ROUTES(state, routes)的入参routes赋值给addRoutes数组,将constantRoutes静态路由数组增加routes;

const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
}
}

// vue中store状态管理,通过actions调用 mutations 中封装的方法来实现对于state更改,
// 这里是vue-element-admin中动态路由的主要判断逻辑发生地方,首先判定用户角色是否包含admin(可能多角色),是则将所有asyncRoutes 加入到constantRoutes,若用户角色没有包含admin,则调用filterAsyncRoutes函数,递归地判定asyncRoutes.roles属性是否有该角色,即是否有权限,将有权限的router赋值accessedRoutes 后加入到constantRoutes;

const actions = {
generateRoutes({ commit }, roles) {
return new Promise(resolve => {
let accessedRoutes
if (roles.includes(‘system’)) {
accessedRoutes = asyncRoutes || []
} else {
accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
}
commit(‘SET_ROUTES’, accessedRoutes)
resolve(accessedRoutes)
})
}
}

//-----------------
// 两个上面使用的方法
function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role))
} else {
return true
}
}

export function filterAsyncRoutes(routes, roles) {
const res = []

routes.forEach(route => {
const tmp = { …route }
if (hasPermission(roles, tmp)) {
if (tmp.children) {
tmp.children = filterAsyncRoutes(tmp.children, roles)
}
res.push(tmp)
}
})

return res
}

export default {
namespaced: true,
state,
mutations,
actions
}


* src/permission.js



> 
> 修改根目录src下的permission.js
> 
> 
> 



if (hasToken) {
if (to.path === ‘/login’) {
next({ path: ‘/’ })
NProgress.done()
} else {
try {
const roles = await store.dispatch(‘user/getInfo’)
await store.dispatch(‘permission/generateRoutes’, roles).then(res => {
router.addRoutes(res)
next({ …to, replace: true })
})
} catch (error) {
await store.dispatch(‘user/resetToken’)
Message.error(error || ‘Has Error’)
next(/login?redirect=${to.path})
NProgress.done()
}
}
} else {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next(/login?redirect=${to.path})
NProgress.done()
}
}


## 问题一:路由守卫死循环


![在这里插入图片描述](https://img-blog.csdnimg.cn/20210301143610569.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzk5MzA2NQ==,size_16,color_FFFFFF,t_70)



> 
> 如图,按上面配置动态路由后,在进入路由守卫时,不断循环,无法正常转发
> 
> 
> 


其实在路由守卫中,只有`next()`是放行,其他的诸如:`next('/logon') 、 next(to) 或者 next({ ...to, replace: true })`都不是放行,而是:**中断当前导航,执行新的导航**


例如现在我有一个守卫,在守卫中我使用`next('/logon')`,肯定有同学认为是会直接跳转到/logon路由:



beforeEach((to, from, next) => {
next(‘/logon’)
}


其实他是这么执行的:



beforeEach((to, from, next) => {
beforeEach((‘/logon’, from, next) => {
beforeEach((‘/logon’, from, next) => {
beforeEach((‘/logon’, from, next) => {
beforeEac… // 一直循环下去… , 因为我们没有使用 next() 放行
}
}
}
}


`next('/logon')`不是说直接去`/logon`路由,而是中断这一次路由守卫的操作,又进入一次路由守卫,就像嵌套一样,一层路由守卫,然后又是一层路由守卫,此时路由守卫进入到第二层时,`to.path`已经不是`/home`了,这个时候才执行`next()`放行操作。  
 如果守卫中没有正确的放行出口的话,会一直`next({ ...to})`进入死循环 !!!


因此你还需要确保在当`addRoutes()`已经完成时,所执行到的这一次`beforeEach((to, from, next)`中有一个正确的`next()`方向出口。  
 **因此想实现动态添加路由的操作的话,代码应该是这样的:**



const hasToken = getToken()[‘Authorization’]
if (hasToken) {
if (to.path === ‘/login’) {
next({ path: ‘/’ })
NProgress.done()
} else {
const hasRoles = store.getters.roles && store.getters.roles.length > 0
if(hasRoles){
next()
}else{
try {
const roles = await store.dispatch(‘user/getInfo’)
await store.dispatch(‘permission/generateRoutes’, roles).then(res => {
router.addRoutes(res)
next({ …to, replace: true })
})
} catch (error) {
await store.dispatch(‘user/resetToken’)
Message.error(error || ‘Has Error’)
next(/login?redirect=${to.path})
NProgress.done()
}
}
}
} else {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next(/login?redirect=${to.path})
NProgress.done()
}
}
})



getInfo({ commit, state }){
return new Promise((resolve, reject) => {
const { roles } = JSON.parse(getUser())
commit(“SET_ROLES”, roles)
resolve(roles)
})
},


## 问题二:addRouters()不生效



> 
> 执行完addRouters()后,我查看了store里的routes,已经有将动态路由添加进去,但是菜单中还是没有显示
> 
> 
> 



> 
> 查看了/layout/components/Sidebar/index.vue,发现使用的是this. 
>  
>  
>  
>  
>  r 
>  
>  
>  o 
>  
>  
>  u 
>  
>  
>  t 
>  
>  
>  e 
>  
>  
>  r 
>  
>  
>  . 
>  
>  
>  o 
>  
>  
>  p 
>  
>  
>  t 
>  
>  
>  i 
>  
>  
>  o 
>  
>  
>  n 
>  
>  
>  s 
>  
>  
>  . 
>  
>  
>  r 
>  
>  
>  o 
>  
>  
>  u 
>  
>  
>  t 
>  
>  
>  e 
>  
>  
>  s 
>  
>  
>  而 
>  
>  
>  不 
>  
>  
>  是 
>  
>  
>  s 
>  
>  
>  t 
>  
>  
>  o 
>  
>  
>  r 
>  
>  
>  e 
>  
>  
>  中 
>  
>  
>  的 
>  
>  
>  , 
>  
>  
>  所 
>  
>  
>  以 
>  
>  
>  我 
>  
>  
>  们 
>  
>  
>  需 
>  
>  
>  要 
>  
>  
>  在 
>  
>  
>  a 
>  
>  
>  d 
>  
>  
>  d 
>  
>  
>  R 
>  
>  
>  o 
>  
>  
>  u 
>  
>  
>  t 
>  
>  
>  e 
>  
>  
>  r 
>  
>  
>  s 
>  
>  
>  ( 
>  
>  
>  ) 
>  
>  
>  后 
>  
>  
>  也 
>  
>  
>  修 
>  
>  
>  改 
>  
>  
>  t 
>  
>  
>  h 
>  
>  
>  i 
>  
>  
>  s 
>  
>  
>  . 
>  
>  
>  
>  router.options.routes而不是store中的,所以我们需要在addRouters()后也修改this. 
>  
>  
>  router.options.routes而不是store中的,所以我们需要在addRouters()后也修改this.router.options.routes的值,或者直接修改下面routes()方法,直接使用store中的routes
> 
> 
> 



routes() {
return this.$router.options.routes
}


**修改后的permission.js**



const roles = await store.dispatch(‘user/getInfo’)
await store.dispatch(‘permission/generateRoutes’, roles).then(res => {
router.addRoutes(res)
router.options.routes = store.getters.routes
next({ …to, replace: true })
})


## 最终版,所有相关文件


* router/index.js



import Vue from ‘vue’
import Router from ‘vue-router’
import Layout from ‘@/layout’

Vue.use(Router)

export const constantRoutes = [
{
path: “”,
redirect: ‘/portal’,
},

{
path: ‘/login’,
component: () => import(‘@/views/login/index’),
},

{
path: ‘/404’,
component: () => import(‘@/views/404’),
},

{
path: ‘/portal’,
component: () => import(‘@/views/portal/index’),
},

{
path: ‘/’,
component: Layout,
redirect: ‘/dashboard’,
children: [{
path: ‘dashboard’,
name: ‘Dashboard’,
component: () =>
import (‘@/views/dashboard/index’),
meta: { title: ‘资源认证平台’, affix: true, icon: ‘dashboard’ }
}]
},

{
path: ‘/user’,
component: Layout,
redirect: ‘/user’,
children: [{

算法刷题

大厂面试还是很注重算法题的,尤其是字节跳动,算法是问的比较多的,关于算法,推荐《LeetCode》和《算法的乐趣》,这两本我也有电子版,字节跳动、阿里、美团等大厂面试题(含答案+解析)、学习笔记、Xmind思维导图均可以分享给大家学习。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

写在最后

最后,对所以做Java的朋友提几点建议,也是我的个人心得:

  1. 疯狂编程

  2. 学习效果可视化

  3. 写博客

  4. 阅读优秀代码

  5. 心态调整

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值