前言
在现代前端开发中,状态管理是构建复杂应用的关键环节。Vuex作为Vue.js的官方状态管理库,为我们提供了集中式的状态管理方案。然而,Vuex存在一个明显的痛点:页面刷新后状态会重置,这给用户体验带来了不小的挑战。
本文将详细介绍如何使用vuex-persistedstate插件实现Vuex状态的持久化缓存,确保用户在刷新页面后仍能保持登录状态、菜单信息、用户偏好设置等重要数据
为什么需要Vuex持久化?
在单页应用(SPA)中,Vuex的状态存储在内存中,当页面刷新时,这些状态会被重置。这意味着:
- 用户登录状态可能丢失,需要重新登录
- 用户的权限菜单和偏好设置无法保存
- 用户的操作填写进度丢失等
为了解决这些问题,我们需要将Vuex状态持久化到浏览器的存储中(如sessionStorage、localStorage)。
实践过程
1. 安装与基础配置
首先安装依赖:
bash
csharp
npm install vuex-persistedstate
# 或
yarn add vuex-persistedstate
2. 创建持久化插件
以下是我们在项目中实际使用的配置:
js
import createPersistedState from 'vuex-persistedstate'
import { getToken } from '@/utils/auth'
export const PERSISTEDSTATE_KEY = 'project-app-store'
/**
* 清除持久化数据
*/
export function clearPersistedState() {
window.sessionStorage.removeItem(PERSISTEDSTATE_KEY)
}
const persistedStatePlugin = createPersistedState({
key: PERSISTEDSTATE_KEY,
storage: {
getItem(key) {
if (hasPersistedData()) {
return sessionStorage.getItem(key)
}
return JSON.stringify({
user: {
token: getToken()
},
menu: {}
})
},
setItem(key, value) {
sessionStorage.setItem(key, value)
},
removeItem(key) {
sessionStorage.removeItem(key)
}
},
reducer(state) {
return {
user: state.user,
menu: state.menu
}
}
})
export default persistedStatePlugin
// 检查本地是否有缓存
export function hasPersistedData() {
try {
const persisted = sessionStorage.getItem(PERSISTEDSTATE_KEY)
if (persisted) {
const parsed = JSON.parse(persisted)
// 检查是否有有效的 token 数据
return !!parsed.user?.token
}
} catch (e) {
console.warn('Failed to check persisted data:', e)
return false
}
return false
}
3. 在Vuex中引入插件
在store的配置文件中引入我们创建的持久化插件:
js
import Vue from 'vue'
import Vuex from 'vuex'
....
import persistedStatePlugin from './plugins/persistedstate'
Vue.use(Vuex)
const store = new Vuex.Store({
....
plugins: [persistedStatePlugin]
})
export default store
配置详解
1. 存储键名(key)
js
key: PERSISTEDSTATE_KEY
这里我们定义了存储的键名,避免与其他应用产生冲突
2. 自定义存储处理
javascript
storage: {
getItem(key) {
if (hasPersistedData()) {
return sessionStorage.getItem(key)
}
return JSON.stringify({
user: {
token: getToken()
},
menu: {}
})
},
setItem(key, value) {
sessionStorage.setItem(key, value)
},
removeItem(key) {
sessionStorage.removeItem(key)
}
}
这里的特殊处理是因为缓存插件开启后,不管有没有本地缓存,都会覆盖store初始化的值,所以需要特殊处理一下,以免token的初始值丢失(本项目token由后端登录鉴权接口写入cookie中,接口调用时,将access_token放在请求头里,request封装axios在store里获取)
3. 状态选择器(reducer)
javascript
reducer(state) {
return {
user: state.user,
menu: state.menu
}
}
通过reducer函数,我们可以选择性地持久化部分状态,避免将敏感或不必要的数据持久化。
4. 工具函数
我们还提供了一些工具函数来增强插件的可用性:
javascript
// 检查是否存在有效的持久化数据
export function hasPersistedData() {
try {
const persisted = sessionStorage.getItem(PERSISTEDSTATE_KEY)
if (persisted) {
const parsed = JSON.parse(persisted)
return !!parsed.user?.token
}
} catch (e) {
console.warn('Failed to check persisted data:', e)
return false
}
return false
}
// 清除持久化数据 在用户登录过期或退出登录时调用
export function clearPersistedState() {
window.sessionStorage.removeItem(PERSISTEDSTATE_KEY)
}
进一步优化建议:
- 可以考虑添加数据加密功能,增强安全性
- 对于大型应用,可以引入状态版本管理机制
如果你有更好的实践方案或建议,欢迎在评论区分享讨论!