解决vue3,动态添加路由,刷新页面出现白屏或者404
1.解决出现刷新页面,出现404的情况
1.问题的出现
在做毕设的时候,在权限路由得到时候,我问通过router**.**addRoute(item)的方式,在路由守卫动态添加路由
刚开始没什么问题,页面的都能正常显示,网络请求也能发送,后来出现了刷新页面,跳转到404
原因:没有将404路由进行动态的添加,而是将他放到了静态路由表里,这就会导致动态的路由会出现404后面,匹配动态路由的时候
上错误代码:
routes = [
{
path: '/',
redirect: '/login',
hidden: true
},
{
path: '/login',
name: 'login',
component: () => import('@/views/Login/index.vue'),
hidden: true
},
{
path: '/register',
name: 'register',
component: () => import('@/views/Register/index.vue'),
hidden: true
},
// 首页
{
path: '/home',
name: 'home',
component: Layout,
redirect: '/home/index',
children: [
{
path: 'index',
meta: {
title: '首页',
icon: 'HomeFilled'
},
component: () => import('@/views/home/index.vue')
}
]
},
{
path: '/personal',
name: 'personal',
component: Layout,
children: [
{
path: 'userinfo',
meta: {
title: '个人信息'
},
component: () => import('@/views/Personal/userinfo.vue')
},
{
path: 'password',
meta: {
title: '修改密码'
},
component: () => import('@/views/Personal/password.vue')
}
]
},
//404
{
path: '/:cachAlll(.*)',
component: () => import('@/components/common/404.vue'),
hidden: true
}
]
解决方法
-
提取出404代码片段
const cachAlll = { path: '/:cachAlll(.*)', component: () => import('@/components/common/404.vue'), hidden: true }
-
追加到处理好的权限列表的末尾
筛选出用户的权限路由函数,后来发现我的这种方法有点笨
`
/**
* 用户权限认证
*/
const permission = userStore.userInfo.permission
function permissionAuth(data) {
return permission?.includes(data)
}
function hasPermission(data) {
let homeMenu = []
data.forEach((item) => {
//有permission的路由才做判断,没有的直接放进数组
if (item.permission && !item.children) {
if (permissionAuth(item.permission)) {
homeMenu.push(item)
}
} else if (item.permission && item.children) {
let obj = {}
if (permissionAuth(item.permission)) {
obj = {
...item,
children: []
}
item.children.forEach((child) => {
if (permissionAuth(child.permission)) {
obj.children.push(child)
}
})
}
// 判断obj是否为空
if (obj.router) {
homeMenu.push(obj)
}
} else {
homeMenu.push(item)
}
})
return homeMenu
}
//router/index.js
let filterRouter = hasPermission(asyncRouter)
filterRouter.push(cachAlll)
我项目采用的vue-router是4.3.3版本
```js
//路由前置守卫
router.beforeEach(async (to, from) => {
console.log('路由前置守卫')
const userStore = useUserStore()
const token = userStore.token
// 1.在白名单
if (whiteList.includes(to.path)) {
return true
}
// 2.不在白名单
if (!whiteList.includes(to.path) && !token) {
console.log('不在白名单')
return '/login'
}
// 3.有token
if (token) {
// 3.1.判断有没有用户信息
if (JSON.stringify(userStore.userInfo) === '{}') {
// 获取用户信息
await userStore.getUserInfo()
}
// 3.2.判断有没有权限路由
if (userStore.permissionRouter.length == 0) {
await userStore.getUserInfo()
let filterRouter = hasPermission(asyncRouter)
//**************************************此处添加向数组404******************************************************
filterRouter.push(cachAlll)
// 添加动态路由
filterRouter.forEach((item) => {
router.addRoute(item)
})
// 打印动态路由以进行调试
console.log('动态路由:', filterRouter)
console.log(router.getRoutes())
userStore.permissionRouter = [...routes, ...filterRouter]
}
return true
}
})
2.白屏现象
如果按照上面那种方法,可以解决刷新页面出现404的问题,但是会出现白屏的现象
但是为什么会出现404,404的出现是因为没有匹配到任务栏的地址,可是我们已经动态的添加了路由,所以为什么检测不到页面呢????
我参考的别人的博客https://blog.csdn.net/qq_37150410/article/details/128012829?fromshare=blogdetail&sharetype=blogdetail&sharerId=128012829&sharerefer=PC&sharesource=weixin_65363325&sharefrom=from_link,采用了他的方法
具体原因就是:路由守卫里进行的动态路由初始化行不通,因为在进路由守卫之前,程序已经进行了路由匹配,结果就是没匹配到任何内容,自然就报错了。
这是我的打印
可以发现问题出现在use(router)这里
因为我们连路由前置守卫都没进去,就已经匹配路由了,动态路由还没添加,就肯定报错了
解决方法:https://blog.csdn.net/qq_37150410/article/details/128012829?fromshare=blogdetail&sharetype=blogdetail&sharerId=128012829&sharerefer=PC&sharesource=weixin_65363325&sharefrom=from_link
也是参考上面这位博主 的文章的方法,但是跟她的处理略有不同
上代码
在路由js文件,我把动态追加路由提取出来了
export async function initRouter(){
const userStore= useUserStore()
await userStore.getUserInfo()
let filterRouter = hasPermission(asyncRouter)
filterRouter.push(cachAlll)
// 添加动态路由
filterRouter.forEach((item) => {
router.addRoute(item)
})
// 打印动态路由以进行调试
console.log('动态路由:', filterRouter)
console.log(router.getRoutes())
userStore.permissionRouter = [...routes, ...filterRouter]
}
router.beforeEach(async (to, from) => {
console.log('路由前置守卫')
const userStore = useUserStore()
const token = userStore.token
// 1.在白名单
if (whiteList.includes(to.path)) {
return true
}
// 2.不在白名单
if (!whiteList.includes(to.path) && !token) {
console.log('不在白名单')
return '/login'
}
// 3.有token
if (token) {
// 3.1.判断有没有用户信息
if (JSON.stringify(userStore.userInfo) === '{}') {
// 获取用户信息
await userStore.getUserInfo()
}
// 3.2.判断有没有权限路由
if (userStore.permissionRouter.length == 0) {
await initRouter()
}
return true
}
})
接下来是最重要的一步
main.js文件在注册router之前,强制初始化一下
async function initMainRouter() {
await initRouter()
app.use(ElementPlus, {
locale: zhCn
})
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(createPinia())
app.use(router)
console.log('入口文件2')
app.mount('#app')
}
initMainRouter()
使用await,强行让挂载等待路由初始化完成,彻底将刷新就空白页的问题解决。------引用上面博主文章的话,这个博主的口才真好