vue-element-admin 刷新页面后跳转登录页面或404页面Bug-解决记录

01 Bug 描述

笔者基于简化版的 vue-element-admin 前端框架 vue-admin-template 进行二次开发。

我在 vue-admin-template 中增加了权限认证和动态路由的功能,即前端根据不同用户角色生成动态路由,并渲染出不同的页面。

增加这个功能之后,项目总是出现刷新页面就直接跳转到404页面,然后系统崩溃的Bug,如图所示:
在这里插入图片描述

02 追溯 Bug

因为觉得是权限认证出的问题,我就开始从这里找Bug,项目中路由层面权限的控制代码 @/permission.js 内容如下:

import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
import getPageTitle from '@/utils/get-page-title'NProgress.configure({ showSpinner: false })
const whiteList = ['/login']router.beforeEach(async(to, from, next) => {NProgress.start()document.title = getPageTitle(to.meta.title)// 获取用户 tokenconst hasToken = getToken()// 具有token 已经登录成功if (hasToken) {// 如果在登录页面直接跳转到主页if (to.path === '/login') {next({ path: '/' })NProgress.done()} else {// 如果在其他页面,判断用户是否已经登录const hasRoles = store.getters.roles && store.getters.roles.length > 0if (hasRoles) {next()} else {// 首次登录 获取用户角色并生成动态路由try {console.log('premission roles', store.getters.roles) // 用于 Debug 查看用户是否成功登录await store.dispatch('user/getInfo')const accessRoutes = await store.dispatch('permission/generateRoutes', store.getters.roles)router.addRoutes(accessRoutes)next({ ...to, replace: true })} catch (error) {await store.dispatch('user/resetToken')Message.error(error || 'Has Error')next(`/login?redirect=${to.path}`)NProgress.done()}}}} else {// 登录失败 跳转到登录页面if (whiteList.indexOf(to.path) !== -1) {next()} else {next(`/login?redirect=${to.path}`)NProgress.done()}}
})router.afterEach(() => {NProgress.done()
})

上面代码中的Debug语句 console.log('premission roles', store.getters.roles) 是我发现Bug所在的关键。

当正常登录时,该语句的输出如下图所示,可以看到用户角色为 ROLE_ADMIN

在这里插入图片描述
而刷新页面后出现 404 界面时,控制台输出的用户信息可以确定用户已经登录成功,但是 Debug 语句输出的用户角色内容为空null
在这里插入图片描述

这时我想到用户信息和用户角色以及动态路由表都存储在src/store/getters.js中如下所示:

const getters = {sidebar: state => state.app.sidebar,device: state => state.app.device,token: state => state.user.token,avatar: state => state.user.avatar,name: state => state.user.name,roles: state => state.user.roles,permission_routes: state => state.permission.routes
}
export default getters

那么用户角色信息 store.getters.roles 为什么会凭空消失呢?

这时我想起 Vuex 作为一个状态管理的插件,虽然可以解决不同组件之间的数据共享和数据持久化,并且具有更高的数据存储安全性;但是,在刷新页面后,Vuex 会重新更新 state ,这时其中存储的数据会丢失,即 store 就会被重置。

03 解决 Bug

已经发现在 vue 项目中,使用 Vuex 做状态管理时,刷新后 store 中存储的数据会被重置,那么该怎么解决这个 Bug 呢?

一种解决方案就是可以把定义刷新前把 store 存入本地 localStorage、sessionStorage、cookie中,他们适用于不同的场景:

  • localStorage:永久储存,重新打开页面时会读取上一次打开的页面数据
  • sessionStorage:储存到关闭为止
  • cookie:不适合存大量数据

这里我们使用折中方案 sessionStorage 将刷新前的数据本地保存,修改 @/App.vue 文件内容如下,实现数据的本地保存

<template><div id="app"><router-view /></div>
</template><script>
export default {name: 'App',created() {// 在页面加载时读取sessionStorage里的状态信息if (sessionStorage.getItem('store')) {this.$store.replaceState(Object.assign({},this.$store.state,JSON.parse(sessionStorage.getItem('store'))))}  // 在页面刷新时将 vuex 里的信息保存到 sessionStorage 里// beforeunload事件在页面刷新时先触发window.addEventListener('beforeunload', () => {sessionStorage.setItem('store', JSON.stringify(this.$store.state))})}
}
</script>

参考资料

vue页面刷新后store内的数据清空

解决vue刷新页面以后丢失store的数据问题


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部