做项目时遇到的这个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()
})