我们这个是后台管理模板,动态路由一般是登录系统后,需要动态新增的路由,也就是我们可以在全局前置守卫里面,配置动态路由。

  • 用户登录成功后,加载动态路由到路由表,如下所示:
// 白名单列表
const whiteList = ['/login']

// 全局前置守卫,路由跳转前执行
router.beforeEach(async (to, from, next) => {

  // token存在的情况
  if (store.userStore.token) {
    if (to.path === '/login') {
      next('/home')
    } else {
      // 登录的时候,只会返回token,用户信息是没有的,在这里初始化登录后的相关信息
      if (!store.userStore.user.id) {
        try {
          // 获取用户信息
          await store.userStore.getUserInfoAction()
          // 获取用户权限信息
          await store.userStore.getAuthorityListAction()
          // 获取字典数据
          await store.appStore.getDictListAction()
        } catch (error) {
          // 请求异常,则跳转到登录页
          store.userStore?.setToken('')
          next('/login')
          return Promise.reject(error)
        }

        // 动态菜单+常量菜单
        const menuRoutes = await store.routerStore.getMenuRoutes()

        // 获取扁平化路由,将多级路由转换成一级路由,因为Vue缓存最多支持二级路由
        const keepAliveRoutes = getKeepAliveRoutes(menuRoutes, [])

        // 添加菜单路由
        asyncRoutes.children?.push(...keepAliveRoutes)
        router.addRoute(asyncRoutes)

        // 上面的路由都匹配不到,则会匹配到错误路由
        router.addRoute(errorRoute)

        next({ ...to, replace: true })
      } else {
        next()
      }
    }
  } else {
    // 没有token的情况下,可以进入白名单
    if (whiteList.indexOf(to.path) > -1) {
      next()
    } else {
      next('/login')
    }
  }
})

// 异步路由,需要全部放在children里面,可以了解一下嵌套路由知识点
const asyncRoutes: RouteRecordRaw = {
  path: '/',
  component: () => import('../layout/index.vue'),
  redirect: '/home',
  children: [
    {
      path: '/home',
      name: 'Home',
      component: () => import('../views/home.vue'),
      meta: {
        title: i18n.global.t('router.home'),
        affix: true
      }
    },
    {
      path: '/profile/password',
      name: 'ProfilePassword',
      component: () => import('../views/profile/password.vue'),
      meta: {
        title: i18n.global.t('router.profilePassword'),
        cache: true
      }
    }
  ]
}
  • 上面会把菜单路由信息,动态的添加到路由表里面。