原因:
- vuex存储的数据只是在页面中,相当于全局变量,页面刷新时vuex里的数据会重新初始化,导致数据丢失
- vuex里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,vuex里面的数据会被重新赋值
解决思路:
- 将vuex的数据直接保存在浏览器的缓存中(sessionStorage、localStorage、cookie)
- 页面刷新后再从浏览器中取出
解决方法一:
-
选择合适的浏览器存储
localStorage – 永久存储在本地,除非主动删除
sessionStorage – 存储在当前tab页,关闭当前tab页就会消失
cookie – 根据设置的有效时间来存储,缺点是内存小不能存储大数据且不易读取,会和后台进行交互
注:一般vue会选择sessionStorage,因为一是vue是单页面应用,操作都是在一个页面跳转路由,二是可以保证打开页面时,sessionStorage的数据为空,而如果是localStorage则会读取上一次打开页面的数据
-
页面刷新的时候,监听浏览器刷新前事件,在浏览器刷新之前就把vuex里的数据保存到sessionStorage中,刷新成功后如果异步请求的数据未返回则直接获取sessionStorage的数据
解决方法二:
Vuex持久化插件(vuex-persistedstate)
-
原理:将vuex的state存在浏览器存储中一份,刷新页面的 一瞬间,vuex数据消失,会去浏览器存储中拿回数据
-
使用方法:
-
目的:让在vuex中管理的状态数据同时储存在本地。可免去自己储存的环节。
-
适用场景:
a:在开发的过程中,像用户信息(名字,头像,token)需要vuex中储存且需要本地储存
b:购物车如果需要未登录状态下也支持,如果管理在vuex中页面需要储存在本地
-
使用步骤:
-
安装vuex的插件vuex-persistedstate来支持vuex的状态持久化
npm i vuex-persistedstate
-
在store文件夹下新建modules文件,在modules下根据项目创建模块化js
-
在index.js文件中引入模块化的js,使用vuex-persistedstate插件对想存储的模块来进行持久化
// 以下代码为我其中一项目中的,可根据自己项目中的自行更改适配 import Vue from 'vue' import Vuex from 'vuex' import createPersistedState from 'vuex-persistedstate' import getters from './getters' import $config from '@/config' Vue.use(Vuex) // https://webpack.js.org/guides/dependency-management/#requirecontext const modulesFiles = require.context('./modules', true, /\.js$/) // 自动引入modules目录下的vuex模块 const modules = modulesFiles.keys().reduce((modules, modulePath) => { const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1') const value = modulesFiles(modulePath) modules[moduleName] = value.default return modules }, {}) const store = new Vuex.Store({ getters, modules, strict: process.env.NODE_ENV !== 'production', // 如果此刻想配置多个选项,将plugins写成一个一维数组,不然会报错。 plugins: [ // 可以有多个持久化实例 createPersistedState({ key: `wyx-${$config.PLATFORM}`, // 状态保存到本地的 key paths: ['app.pageTab', 'common.menuInfo', 'aliyunOss', 'common.noviceDerverInfo', 'common.shopStatus', 'common.shopDetailData', 'app.marketingTab', 'addEditGoods.checkCycleList'], // 要持久化的状态,在state里面取 storage: { // 存储方式定义 getItem: (key) => localStorage.getItem(key), // 获取 setItem: (key, value) => localStorage.setItem(key, value), // 存储 removeItem: (key) => localStorage.removeItem(key) // 删除 } }) ] }) export default store
-
-
参数说明:
createPersistedState([options])使用给定的选项创建插件的新实例。可以提供以下选项来配置您的特定需求的插件:
key :存储持久状态的键。(默认:vuex)
paths :部分持续状态的任何路径的数组。如果没有路径给出,完整的状态是持久的。(默认:[])
reducer :一个函数,将被调用来基于给定的路径持久化的状态。默认包含这些值。
subscriber :一个被调用来设置突变订阅的函数。默认为store => handler => store.subscribe(handler)
storage :而不是(或与)getState和setState。默认为localStorage。
getState :将被调用以重新水化先前持久状态的函数。默认使用storage。
setState :将被调用来保持给定状态的函数。默认使用storage。
filter :将被调用来过滤将setState最终触发存储的任何突变的函数。默认为() => true
解决方法三:
插件vuex-along
原理同vuex-persistedstate
使用:
import Vue from 'vue';
import Vuex from 'vuex';
import createVuexAlong from "vuex-along";
const moduleA = {
state: {
a1: "hello",
}
};
const store = new Vuex.Store({
state: {
count: nll
token:''",
},
mutations: {
set_count: (state, payload) => {
state.count= payload
},
set_token: (state, payload) => {
state.token = payload
},
plugins: [
createVuexAlong({
name: "hello-vuex-along", // 设置保存的集合名字,避免同站点下的多项目数据冲突
local: {
list: ["ma"],
isFilter: true // 过滤模块 ma 数据, 将其他的存入 localStorage
},
session: {
list: ["count", "ma.a1"] // 保存 count 和模块 ma 中的 a1 到 sessionStorage
}
//如果对于sessionstorage不进行任何操作,也可将session设为false
})
]
});
参数说明:
VuexAlongOptions
字段 | 必选 | 类型 | 描述 |
---|---|---|---|
name | 否 | string | 设置本地数据集合的名字,默认为vux-along |
local | 否 | Object | localStorage的配置,见WatchOptions表格 |
session | 否 | Object | sessionStorage的配置,见WatchOptions表格 |
justSession | 否 | Boolean | 仅使用sessionStorage |
WatchOptions
字段 | 必选 | 类型 | 描述 |
---|---|---|---|
list | 是 | String[] | 需要监听的属性名或模块名的字符串列表 |
isFilter | 否 | Boolean | 过滤list中的字段,而非保存 |
注:list的四种写法
// 什么都不缓存
{
list: [ '' ],
}
// 全部缓存
{
list: [ ],
}
// 指定缓存
{
list: [ 'user' ],
}
// 除了这几个,其他的都缓存
{
list: [ 'user', 'class' ],
isFilter: true
}
数据清理:
window.clearVuexAlong(local = true, session = true):void;
clearVuexAlong() // localStorage 和 sessionStorage 都会被清理
clearVuexAlong(true,false) // 只清理 localStorage
clearVuexAlong(false,true) // 只清理 sessionStorage