动态路由-刷新页面时的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(); });