解决页面刷新vuex丢数据问题的两种方法(详解)
问题描述首先,关于页面刷新vuex丢数据的问题,其实另一种描述方式是:vuex中页面刷新数据以及初始化问题个人笨见:vuex的数据不是丢失,而是初始化,返回初始值,返回原点。关于vuex的使用,本文不再赘述。具体可以参考之前的文章:https://segmentfault.com/a/11...vuex可以理解为公共空间。所有组件都可以共享这个空间的状态数据。每个人都可以(修改或读取)这个空间的数据。但是这个空间的数据状态是有初始值的,比如页面上的菜单数据信息,因为菜单信息需要作为全局共享数据存储在vuex中。状态仓库中有一个menuArr。初始值是一个空数组。这个空数组存放的是后台传来的动态菜单的数组数据。关于动态菜单可以看一篇文章:https://segmentfault.com/a/11...access项目的初始页面是登录页面。用户登录成功后,会发送请求获取后台返回的动态菜单的数据,然后将这些数据以vuex中的state存储在menuArr中,同时跳转页面时间去项目的主页。此时页面左侧的菜单栏组件读取vuex中的menuArr数据并渲染,用户就可以正常操作了。但!当用户刷新时(比如在首页刷新),路由不会改变,依然在首页。但是:无论是.vue组件中data中的数据还是vuex中state中的数据,都会回到初始状态,所以vuex中的menuArr数组会变成一个空数组,而且因为vue是响应式的,当menuArr为空数组时,左边的菜单栏组件什么也渲染不了,就没了,所以看起来像:页面刷新数据丢失分析清楚问题原因,下一步就是想办法解决这个问题。解决方案1在本地存储登录页面的副本。在login.vue组件中的登录中,我们触发动作。请求的接口可以写在动作中,也可以写在组件中。因为这里需要复用action,所以我在action中写了request。/*login.vue页面*/点击登录
vuex中的naviBar模块/*vuex中的naviBar模块*///为了发送请求,你需要一个vue实例importVuefrom'vue'constthat=newVue()/*vuex数据刷新丢失,解决方法一,在本地保存一份*/constnaviBar={state:{menuArr:JSON.parse(sessionStorage.getItem('menuArr'))?JSON.parse(sessionStorage.getItem('menuArr')):[]},mutations:{setMenu(state,payload){state.menuArr=payload},},actions:{asyncgetMenu({commit},menu){letres=awaitthat.$api.getMenuData()console.log('菜单数据',res);sessionStorage.setItem('menuArr',JSON.stringify(res.data))//本地存储一个commit("setMenu",res.data)//提交mutation},},namespaced:true}exportdefaultnaviBar是vuex中需要使用数据的地方,也就是home。在vue的首页,直接使用computed属性获取对应的vuex数据,在html中使用computed:{menuArr(){returnthis.$store.state.naviBar.menuArr}}方案分析该方案解决了问题,但是如果用户在浏览器的Application中手动清除保存在sessionstorage中的vuex数据,当用户刷新的时候还是会丢失,左边的菜单依然会没有。路人甲:用户会这样操作吗,黑色问号?所以我们考虑使用第二种方法。当页面刷新时,重新发送请求即可(无需使用浏览器存储)。解决方法是刷新页面重新发送login.vue页面,不用移动vuex中的naviBar模块,当页面刷新重新发送请求时,vuex不需要写的太复杂。//为了发送请求,需要有一个vue实例importVuefrom'vue'constthat=newVue()/*vuex数据刷新丢失,解决方法2,然后重新发送请求*/constnaviBar={state:{menuArr:[]},mutations:{setMenu(state,payload){state.menuArr=payload},},actions:{asyncgetMenu({commit},menu){letres=awaitthat.$api.getMenuData()commit("setMenu",res.data)},},namespaced:true}exportdefaultnaviBarouterpageresendrequest注意是外视图,根据视图结构选择位置项目。我写在home.vue中,因为这个页面还需要用到vuex中的menuArr数据,也是外视图exportdefault{name:"Home",created(){/*注意,因为数组是引用数据类型,所以[]不等于[],这里转成字符串进行比较。如果vuex中的menuArr不是初始值,则再次发送请求,重新获取菜单栏中的数据。添加判断也算是一种优化。如果没有,则在用户登录时发送一次,在主页组件加载时也会发送一次请求。也就是减少发送请求的数量*/}},computed:{menuArr(){returnthis.$store.state.naviBar.menuArr;},},...}方案分析该方案达到了效果,减少了本地存储的使用,但是增加了请求次数和次数。与之前的方案相比,各有优缺点,具体用哪一种看业务。其他方案也可以使用插件包解决,比如vuex-persistedstate等...