在 Vue.js 应用中,使用 Vuex 状态管理库时,页面刷新会导致 Vuex 中的状态丢失,因为 Vuex 的状态是存储在内存中的。为了在页面刷新后仍然保留这些状态,你可以采用以下几种策略来持久化 Vuex 的状态:
-
使用
Local Storage
或Session Storage
- 可以在页面加载时从
Local Storage
或Session Storage
中读取状态,并将其恢复到 Vuex store 中。 - 页面刷新前,可以将 Vuex 的状态保存到
Local Storage
或Session Storage
中。
- 可以在页面加载时从
-
重新请求接口从后端获取
- 在路由守卫
beforeEach()
中发送请求, 再次将数据存储到 vuex store 中
- 在路由守卫
-
使用 Vuex 插件
- 有一些现成的插件可以帮助你更容易地实现状态持久化,例如
vuex-persistedstate
。
- 有一些现成的插件可以帮助你更容易地实现状态持久化,例如
使用 Local Storage
或 Session Storage
// store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
userMsg: null,
},
mutations: {
setUserMsg(state, payload) {
state.userMsg = payload;
localStorage.setItem('userMsg', JSON.stringify(payload));
},
},
});
封装 beforeEach()
函数重新请求接口获取
// src/permission.js
import store from '@/store';
import { getUserInfo, } from '@/api/user';
const whiteList = ['/login', '/404']
router.beforeEach((to, from, next) => {
if (store.getters.token) { // determine if there has token
/* has token*/
if (to.path === '/login') {
next({ path: '/' });
} else {
if (store.getters.roles.length === 0) {
// 调用接口获取数据
getUserInfo().then(({ data }) => {
console.log('data::: ', data);
store.commit('SET_ROLES', data.roles);
store.commit('SET_ROLES_TYPE', data.roleType);
store.commit('SET_USERIFNO', data.sysUser);
console.log('store.user', store.state);
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
} else {
next();
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next('/login')
}
}
})
使用 Vuex 插件
vuex-persistedstate 是一个用于将 Vuex store 中的状态持久化的插件。它可以将状态存储在浏览器的 Local Storage、Session Storage 或 Cookie 中,并在页面重新加载时恢复这些状态。
安装 vuex-persistedstate
:
npm install vuex-persistedstate --save
# 或者
yarn add vuex-persistedstate
配置 vuex-persistedstate
// store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
userMsg: null,
},
mutations: {
setUserMsg(state, payload) {
state.userMsg = payload;
},
},
});
// 使用插件
store.plugin(createPersistedState({
paths: ['userMsg'],
}));
export default store;
参数选项
createPersistedState 接受一个对象作为参数,其中包含以下可选配置项:
key
: 存储数据时使用的键名,默认为 ‘vuex’。storage
: 存储数据的位置,默认为window.localStorage
。也可以设置为window.sessionStorage
或自定义存储方法。paths
: 指定需要持久化的state
属性路径数组,默认为undefined
,表示持久化整个state
。reducer
: 类似于 Redux 的reducer
函数,用于决定哪些状态应该被持久化,默认为undefined
。transformer
: 在存储数据前进行转换的函数,默认为undefined
。filter
: 用于过滤状态的函数,默认为undefined
。purgeOnEachLoad
: 是否在每次加载时清除存储的数据,默认为false
。merge
: 是否合并状态而不是替换,默认为false
。silent
: 是否禁用日志输出,默认为false
。strictMode
: 是否启用严格模式,默认为false
。在严格模式下,如果持久化失败则抛出错误。
示例
import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 0,
user: null,
settings: { theme: 'light' },
},
mutations: {
increment(state) {
state.count++;
},
setUser(state, user) {
state.user = user;
},
setTheme(state, theme) {
state.settings.theme = theme;
},
},
});
// 使用插件
store.plugin(createPersistedState({
key: 'my-app',
storage: window.localStorage,
paths: ['count', 'user', 'settings.theme'], // 仅持久化这些路径
}));
export default store;
注意事项: 如果使用 vuex-persistedstate,记得在生产环境中配置合适的 options,例如加密或选择合适的存储方式(Local Storage vs Session Storage)。