使用vue-router添加动态路由时遇到的坑

发布时间 2023-10-09 15:09:07作者: sen_hf

在开发后台管理的时候,用户登录时需要根据权限来分配路由,这时候可以在路由守卫里通过router.addRoute()方法动态添加路由。

import router from './router'
import store from './store'
import storage from '@/utils/storage'
import { asyncRoute } from "@/router/routers";



router.beforeEach(async (to, from, next) => {
  // 检查是否存在有效的 token,如果存在,表示用户已经进行了身份验证,允许放行
  if (storage.local.get('token')) {
    /* 有 token 就放行*/
    if (to.path === '/login') {
      // 如果目标路径是 /login,且用户已经登录,则不需要再次访问 /login 页面,直接跳转到 /home 页面,放行
      next('/home')
    } else {
      // 检查是否已经获取权限列表
      if (!store.state.user.userInfo.id) {
        let user_id = storage.local.get('user_id')
        await store.dispatch('user/getUserInfo', user_id)
        asyncRoute.forEach(route => {
          console.log(route);
          router.addRoute(route); // 使用 addRoute() 方法添加路由
        });
        next({ ...to, replace: true }); // 使用 `replace: true` 防止导航冲突
      } else {
        next()
      }
    }
  } else {
    if (to.path === '/login') {
      next()
    } else {
      next('/login')
    }
  }
});


router.afterEach(() => {
})

这里遇到了两个坑

报错1:Error: Redirected when going from "/login" to "/home" via a navigation guard.

原因:vue-router路由版本更新产生的问题,导致路由跳转失败抛出该错误,但并不影响程序功能,可以在路由文件里面添加以下代码解决

const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location, onResolve, onReject) {
    if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
    return originalPush.call(this, location).catch(err => err)
}

问题2:我的代码里面路由分成两部分,一个是常量路由,另一个是动态路由,在我们使用router.addRoute()添加动态路由时,常量路由是已经加载好了的,如果常量路由里面有404路由,那么会导致我们跳转路由的时候跑到404路由去

原因:vue-router查找路由时,是按顺序去查找,如果你访问的路由在404路由之后,那么他就会再找到404路由时给你跳转,解决方法就是把404路由,在所有的路由加载好之后再添加进去

//任意路由
export const anyRoute = [{
    //404
    path: '/404',
    component: () => import('@/view/404/index.vue'),
    name: 'NotFound',
    meta: {
        title: 'NotFound',
        hidden: true,
        icon: 'el-icon-loading',
    },
}, {

    //任意路由
    path: '/:pathMatch(.*)*',
    redirect: '/404',
    name: 'Any',
    meta: {
        title: '任意路由',
        hidden: true,
        icon: 'DataLine',
    },
}]


// 然后再添加动态路由的方法里,把它放再数组的末尾
 let addRoutes = [...asyncRoute, ...anyRoute]
 addRoutes.forEach(route => {
     router.addRoute(route); // 使用 addRoute() 方法添加路由
 });