vue项目 三种解决vuex页面刷新数据丢失的方法【2021-08-19】
1、问题描述:一般在登录成功的时候需要把用户信息,菜单信息放置vuex中,作为全局的共享数据。但是在页面刷新的时候vuex里的数据会重新初始化,导致数据丢失。因为vuex里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,vuex里面的数据就会被重新赋值。2、解决办法:(1)、分析:定义刷新前把store存入本地localStorage、sessionStorage、cookie
1、问题描述:
一般在登录成功的时候需要把用户信息,菜单信息放置vuex中,作为全局的共享数据。但是在页面刷新的时候vuex里的数据会重新初始化,导致数据丢失。因为vuex里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,vuex里面的数据就会被重新赋值。
2、解决思路:
办法一:在页面刷新的前将vuex中的数据直接保存到浏览器缓存中(sessionStorage)
办法二:在页面刷新路由跳转前再次请求远程数据,使之动态更新vuex数据(该请求必须是在路由跳转前,以防页面已经加载完成了,还没有获取到后台返回的数据)
办法三:在页面刷新路由跳转前再次请求远程数据,并且在页面刷新前将vuex的数据先保存至sessionStorage(以防请求数据量过大页面白屏时间过长)
分析:
办法一:缺点是不安全,不适用大数据量的存储;
办法二:适用于少量的数据,并且不会出现网络延迟,否则白屏时间会长;
办法三:办法一和办法二一起使用;
3、实现:
(1)、分析:
1、选择合适的浏览器存储 (同一个域名下,不同页面的localStorage是共享的,sessionStorage不共享 )
localStorage:是永久存储在本地,重新打开页面时会读取上一次打开的页面数据,不断触发localStorage.setItem()方法对性能不是特别友好,而且一直将数据同步到localStorage中似乎就没必要再用vuex做状态管理,直接用localStorage即可;
sessionStorage:是储存到关闭为止;
cookie:则根据你设置的有效时间来存储,但缺点是不能储存大数据且不易读取,会和后台进行交互。
本方法选择的是sessionStorage,选择的原因是由于vue是单页面应用,操作都是在一个页面跳转路由,另一个原因是sessionStorage可以保证打开页面时sessionStorage的数据为空,而如果是localStorage则会读取上一次打开页面的数据。
2、方案选择(由于state里的数据是响应式,所以sessionStorage存储也要跟随变化,而且只能通过mutations来改变state中的值。首先在用户登录成功之后,然后把用户信息,菜单信息通过actions分发保存至vuex中。)
页面刷新的时候异步请求后台数据,然后动态更新vuex中的数据,当网络延迟、数据量大的情况下,此时还没等vuex获取到后台返回的数据,如果让页面加载就会造成数据丢失,如果不加载就会造成白屏时间延长。所以该解决方案就是:监听浏览器刷新前事件,在浏览器刷新之前就把vuex里的数据保存至sessionStorage中,刷新成功后如果异步请求的数据还没返回则直接获取sessionStorage里的数据,否则获取vuex里的数据。(只有刷新后还没取到后台数据,才会从sessionStorage里取。确保数据的安全性,就算获取sessionStorage里的数据也是安全的,因为每次刷新都会重新赋值,不必担心数据被篡改问题,其次就是对sessionStorage里的数据做了加密操作)
(2)、方法:
办法一:
监听页面是否刷新,如果页面刷新了,将state对象存入到sessionStorage/localStorage中。页面打开之后,判断sessionStorage/localStorage中是否存在state对象,如果存在,则说明页面是被刷新过的,将sessionStorage/localStorage中存的数据取出来给vuex中的state赋值。如果不存在,说明是第一次打开,则取vuex中定义的state初始值。
beforeunload事件在页面刷新时进行触发,可以监听这个方法,让页面在刷新前存store到sessionStorage中。
具体做法是在App.vue的created()周期函数中下如下代码:
//1、全局监听,页面刷新的时候将store里state的值存到sessionStorage中,然后从sessionStorage中获取,
//再赋值给store。然后再把session里面存的删除即可,相当于中间件的作用。
//在页面加载时读取sessionStorage里的状态信息
//vuex 单向数据流,推荐的commit 改变state数据
if (sessionStorage.getItem("store")) {
this.$store.replaceState(
Object.assign({},this.$store.state,JSON.parse(sessionStorage.getItem("store")))
);
sessionStorage.removeItem("store")
}
//2、在页面刷新时将vuex里的信息保存到sessionStorage里
window.addEventListener("beforeunload", () => {
sessionStorage.setItem("store", JSON.stringify(this.$store.state));
});
办法二:
页面的刷新会触发路由的beforeEach函数,拦截路由的跳转异步请求后台数据,等数据返回存入vuex,再跳转路由。
router.beforeEach((to, from, next) => {
if (!getToken()) {
location.href = location.origin
} else if (to.name === 'login') { // 前往的是登录页
next({ name: 'error-403' })
NProgress.done()
} else if (to.name && to.name.indexOf('error') !== -1) { // 判断是否是错误页面
next()
} else if ((!to.path || to.path === '/') && to.name !== 'home') { // 通过name跳转 路径没有权限时path为/ 跳转到404
next({ name: 'error-404' })
} else {
checkUser(next, to, router)
}
})
//js
import { removeToken } from '@/utils/cookies'
import { findHomePage } from '@/utils/common'
import store from '@/store'
export const checkUser = async (next, to, router) => {
next = _getNewNext(next, to.name)
if (!store.getters.userInfo.userId) {
try {
let { authPath } = await store.dispatch('user/setUserInfo')
let rawAppRouter = await store.dispatch('user/setAuth', authPath)
let error404Page = { path: '/*', name: 'error-404', meta: { title: '404-页面不存在' }, component: () => import(`@/views/errorPage/404`) }
router.addRoutes([...rawAppRouter, error404Page])
let foundHomePages = findHomePage(rawAppRouter)
if (to.path === '/' && foundHomePages) {
next({ ...foundHomePages, replace: true })
} else {
next({ ...to, replace: true })
}
} catch (e) {
removeToken()
location.href = location.origin
}
} else {
next()
}
}
//vuex
actions: {
// 获取用户信息
setUserInfo ({ commit, dispatch }) {
return new Promise((resolve, reject) => {
getUserInfo().then(res => {
if (res.result === 1) {
commit('SET_USER', res.data)
dispatch('setSysMenu')
getAuthMenu().then(authres => {
if (authres.result === 1) {
commit('SET_EXTRA_AUTH', authres.data.extraAuth)
commit('SET_MAINTAIN_PATH', authres.data.maintainPath)
resolve(authres.data)
} else {
reject(authres.msg)
}
}, (err) => {
reject(err)
})
} else {
reject(res.msg)
}
}, (err) => {
reject(err)
})
})
}
}
办法三:
更多推荐
所有评论(0)