做项目时遇到的这个bug,因为除了跳404之外也没太大影响,之前就一直放着没管,现在项目基本功能实现了,转头处理了一下,现在在这里记录一下解决方法
这个bug的具体情况是:设置了动态路由之后,不同的用户登录之后显示了不同的侧边栏,在侧边栏点击菜单,渲染对应路由页面没有任何问题,但是在动态路由上当我刷新浏览器时会出现404(这种情况只出现在动态路由上,静态路由刷新没问题)。
动态路由设置不成功的可以看我之前的文章:vue-element-template 设置权限管理配置文件 \ vue用户权限管理_vue template设置-CSDN博客
解决方法一
由于通配路由需要放在整个路由的最后,所以不能放在asyncRouterMap的最后,但是也不能直接放在constantRoutes的最后,因为在动态路由在刷新时会跳转到404,因为刷新是动态路由还没加载进来,但是页面已经进行了跳转,找不到匹配的路由,最后会去到通配路由。
解决方法:
把下面这个路由从constantRoutes的最后一行转移到asyncRoutes的最后一行即可!
// 404 page must be placed at the end !!! { path: '*', redirect: '/404', hidden: true }
复制
解决方法二:
在使用的过程中,加入权限模块后,刷新后权限控制的页面就默认跳转到404页面了,原因是权限控制的路由模块是动态添加进去的,而我的404监听路由是在默认路由里面的,优先级比动态路由要高,所以刷新后默认先被404接管了,改一下,把404监听路由注释掉需要手动在动态路由加载后,再把通配路由加上去,所以有了解决方法二
解决方法二:
src/router/index.js,去静态路由里把404路由注释掉
// 静态路由,所有人可见 export const constantRoutes = [ { path: '/login', component: () => import('@/views/login/index'), // hidden为true表示在侧边栏不显示 hidden: true }, { path: '/', component: Layout, redirect: '/dashboard', // 二级路由 children: [{ path: 'dashboard', name: 'Dashboard', component: () => import('@/views/dashboard/index'), meta: { title: '首页', icon: 'dashboard' } }] }, { path: '/404', component: () => import('@/views/404'), hidden: true }, // 把这里注释掉,或者删掉 // { path: '*', redirect: '/404', hidden: true } ]
复制
然后修改文件: /src/permission.js,具体位置是下面这段代码中注释后面两行
const res = await store.dispatch('user/getInfo') let roles = res.info.auth_list const accessRoutes = await store.dispatch('permission/GenerateRoutes', roles) let old = JSON.parse(JSON.stringify(router.options)) router.addRoutes(accessRoutes) // 在这动态添加最后的通配路由,确保先有动态路由、再有通配路由,解决动态路由刷新会跳转到404问题 let lastRou = [{ path: '*', redirect: '/404' }] router.addRoutes(lastRou) let newr = JSON.parse(JSON.stringify(router.options)) next({ ...to, replace: true })
复制
/src/permission.js完整代码【可能每个人的不同,建议对照修改而不是复制】
// 引入路由器router import router from './router' // 引入仓库 import store from './store' // 引入ele的提示组件 import { Message } from 'element-ui' // 引入交互进度条 import NProgress from 'nprogress' // progress bar import 'nprogress/nprogress.css' // progress bar style // 从cookie中获取token,登录了就有cookie import { getToken } from '@/utils/auth' // get token from cookie // 得到页面的title import getPageTitle from '@/utils/get-page-title' // 配置nprogress NProgress.configure({ showSpinner: false }) // NProgress Configuration // 白名单,不需要登录就能进入的路由 const whiteList = ['/login'] // no redirect whitelist // 全局前置路由守卫 router.beforeEach(async(to, from, next) => { //开启进度条 NProgress.start() //给页面的title赋值 document.title = getPageTitle(to.meta.title) // 从cookie中拿到token,有的话就放行,determine whether the user has logged in const hasToken = getToken() if (hasToken) { if (to.path === '/login') { // if is logged in, redirect to the home page next({ path: '/' }) NProgress.done() } else { // 获取用户信息 // const hasGetUserInfo = store.getters.name const hasRoles = store.getters.roles && store.getters.roles.length > 0// 权限控制 console.log('roles:',store.getters.roles) // if (hasGetUserInfo) { if (hasRoles) { console.log('执行了1') next() } else { console.log('执行了2') try { // get user info 重新获取用户信息 // await store.dispatch('user/getInfo') // 权限控制 console.log('tore.getters.roles:',store.getters.roles) const { roles } = await store.dispatch('user/getInfo') // 在角色权限基础上生成动态路由表 const accessRoutes = await store.dispatch('permission/generateRoutes', roles) console.log('accessRoutes:',accessRoutes) router.options.routes = store.getters.permission_routes // 动态添加可访问路由 router.addRoutes(accessRoutes) // 在这动态添加最后的通配路由,确保先有动态路由、再有通配路由,解决动态路由刷新会跳转到404问题 let lastRou = [{ path: '*', redirect: '/404' }] router.addRoutes(lastRou) console.log('输出的store:',store) next({...to, replace: true }) // next() } catch (error) { // remove token and go to login page to re-login 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) { // in the free login whitelist, go directly next() } else { // other pages that do not have permission to access are redirected to the login page. next(`/login?redirect=${to.path}`) // 关闭进度条 NProgress.done() } } }) // 全局后置路由守卫 router.afterEach(() => { // finish progress bar NProgress.done() })
复制