动态路由-刷新页面时的 短暂404 bug修复

发布时间 2023-07-02 22:59:12作者: JohnnyLei

动态路由-刷新页面时的bug修复
1.问题说明

如果我们手动刷新浏览器网页,会发现跳到了404页面
对于addRoute添加的路由,在刷新时会白屏

 


2.问题分析
解决页面刷新时,页面 404 问题

在静态路由后面有一个路由通配符,addRoutes添加的路由是异步添加的。
路由设置中的404页处在中间位置,而不是所有路由的末尾了,path:'*' 导致可以匹配任意页面
解决动态路由,刷新页面白屏问题

已知 Vue- router 的Bug
凡是 addRoutes 动态添加的路由,必须在重新调用一下 next() 并且需要手动指定路径才可以。
3.解决
(1) 解决页面刷新时,页面 404 问题

把404页改到路由配置的最末尾就可以了

 

filterRoutes.push(
    { path: '*', redirect: '/404', hidden: true }
  )
next({
    path: to.path, // 保证路由添加完了再进入页面 (可以理解为重进一次)
    replace: true // 重进一次, 不保留重复历史
  })

完整代码

router.beforeEach(async(to, from, next) => {
  // 设置当前页面标题
  document.title = getPageTitle(to.meta.title)

  // 获取 token
  const token = store.state.user.token

  // 显示进度条效果
  NProgress.start()

  // 判断 token 是否存在
  if (token) {
    // 是否是登录页面 、
    if (to.path === '/login') {
      // 如果有 token,访问登录页面,跳转到主页
      next('/')
    } else {
      // 如果有 token,访问不是登录页面,直接放行

      // 1.判断是否存在用户信息(已经将用户信息存到 Vuex 中)
      if (!store.getters.userId) {
        // 2.如果没有用户信息,需要获取用户信息 --> 用户权限信息

        // ** 获取用户信息的时机:**
        // 1.因为依赖 token 去获取用户数据,所以必须要在获取了token 之后才能调用这个 action 函数
        // 2.因为跳转到首页之后就要显示数据了,所以要求我们在跳转进入首页之前就提前拿回用户个人数据
        const menus = await store.dispatch('user/getUserInfo')

        // 3.根据后台返回的权限信息,从本地预置的 8 个路由里面筛选出当前用户有权访问的路由
        const filterRoutes = asyncRoutes.filter(route => {
          // 获取到每一个路由规则的名称
          const routeName = route.children[0].name
          // 判断获取到的路由名称在不在 menus 权限信息中
          return menus.includes(routeName)
        })

        // 解决页面刷新 404 的问题
        // 就是将通配符放置到筛选好的路由最后面
        filterRoutes.push({ path: '*', redirect: '/404', hidden: true })

        // 通过 addRoutes 动态添加的路由,是存到内存中的,并不会对 routes 产生影响
        router.addRoutes(filterRoutes)

        // 5.左侧菜单是从 Vue-router 中的 routes 获取的数据进行渲染,将左侧菜单数据获取方式进行调整(Vuex)
        // 将动态路由传递给 mutation 方法,进行合并
        store.commit('permission/setRoutes', filterRoutes)

        // 通过 addRoutes 添加的路由,访问以后可能存在白屏的问题
        // 原因是 Vue-router 的已知 Bug
        // 之前是没有这些动态路由的,然后我们使用 addRoutes 添加以后才有的路由规则
        // 如果这时候想访问动态添加的路由,必须手动告诉 Vue-router 我要去哪里
        next({ path: to.path, replace: true }) // 会调用 router.replace 方法,清空之前的浏览历史,等于是重新进入路由
      }

      // ** 动态路由的处理时机:**
      // 1.先获取到用户信息
      // 2.跳转之前
      // ** 思路:**
      // 1.判断是否存在用户信息(已经将用户信息存到 Vuex 中)
      // 2.如果没有用户信息,需要获取用户信息 --> 用户权限信息
      // 3.根据后台返回的权限信息,从本地预置的 8 个路由里面筛选出当前用户有权访问的路由
      // 4.使用 Vue-router 提供的 addRoutes 方法,将筛选出来的路由添加到路由对象中
      // 5.左侧菜单是从 Vue-router 中的 routes 获取的数据进行渲染,将左侧菜单数据获取方式进行调整(Vuex)

      next()
    }
  } else {
    // 判断访问的路由在不在白名单
    if (whiteList.includes(to.path)) {
      // 如果没有 token,但在白名单中,则放行
      next()
    } else {
      // 如果没有 token,也不在白名单中,则跳转到登录页
      next('/login')
    }
  }

 
})
//手动强制关闭一次  为了解决 手动切换地址时  进度条的不关闭的问题

router.afterEach(() => { NProgress.done(); });