大家好,我是小杨,一个经历过Vuex数据"人间蒸发"惨案的老司机。上周还在加班赶工,第二天打开项目发现购物车空了?用户登录状态丢了?别急!今天就用冰箱存食物的比喻,教你守住Vuex里的每一份数据!
(文末附赠【防丢代码套餐】,直接复制就能用~)
一、❄️ 数据丢失的五大案发现场
案发现场1:页面刷新 → 冰箱断电
// store里的数据就像断电后的冰箱
state: {
cartItems: [] // 刷新后:空!💔
}
案发现场2:浏览器隐身模式 → 冰箱没插电
// 本地存储无法使用
localStorage.getItem('user') // 返回null
案发现场3:用户手动清除缓存 → 熊孩子清空冰箱
案发现场4:异步操作未完成 → 外卖还没送到就关冰箱
actions: {
async fetchUser({ commit }) {
const user = await 我.调接口() // 如果刷新页面...
commit('SET_USER', user) // 可能永远执行不到!
}
}
案发现场5:SSR hydration失败 → 冰箱门没关严
// 服务端渲染时,客户端初始化状态不匹配
window.__INITIAL_STATE__ = {...} // 传输过程中丢失
二、🔒 五道防盗门方案
方案1:本地存储持久化(给冰箱加发电机)
// store初始化时读取
const user = JSON.parse(localStorage.getItem('user') || 'null')
const store = new Vuex.Store({
state: { user },
plugins: [
store => {
// 状态变化时自动保存
store.subscribe((mutation, state) => {
localStorage.setItem('user', JSON.stringify(state.user))
})
}
]
})
方案2:vuex-persistedstate插件(智能保鲜膜)
npm install vuex-persistedstate
import createPersistedState from 'vuex-persistedstate'
const store = new Vuex.Store({
plugins: [
createPersistedState({
paths: ['user', 'cart'] // 只持久化指定模块
})
]
})
方案3:会话管理(临时小冰柜)
// 使用sessionStorage替代(标签页关闭时清除)
createPersistedState({
storage: window.sessionStorage
})
方案4:防抖保存(省电模式)
let saveTimer
store.subscribe((_, state) => {
clearTimeout(saveTimer)
saveTimer = setTimeout(() => {
localStorage.setItem('store', JSON.stringify(state))
}, 1000) // 1秒防抖
})
方案5:SSR数据脱水/注水(冷链运输)
// 服务端
context.state = store.state
// 客户端
if (window.__INITIAL_STATE__) {
store.replaceState(window.__INITIAL_STATE__)
}
三、💼 实战代码套餐
套餐A:用户登录状态保卫战
// store/modules/user.js
export default {
state: () => ({
token: null,
profile: null
}),
mutations: {
LOGIN(state, { token, profile }) {
state.token = token
state.profile = profile
// 同步保存到本地存储
localStorage.setItem('auth', JSON.stringify({ token, profile }))
}
},
actions: {
initAuth({ commit }) {
const auth = JSON.parse(localStorage.getItem('auth'))
if (auth) commit('LOGIN', auth)
}
}
}
套餐B:购物车数据抢救方案
// store/plugins/cartPersistence.js
export default store => {
// 初始化时读取
const savedCart = localStorage.getItem('cart')
if (savedCart) {
store.commit('cart/RESTORE_CART', JSON.parse(savedCart))
}
// 监听变化
store.subscribe((mutation, state) => {
if (mutation.type.startsWith('cart/')) {
localStorage.setItem('cart', JSON.stringify(state.cart.items))
}
})
}
四、🚨 小杨的避坑指南
-
敏感信息别乱存
- ❌ 把用户密码存在localStorage
- ✅ 只存token,及时过期
-
大体积数据要谨慎
// 超过5MB可能引发性能问题 localStorage.setItem('hugeData', JSON.stringify(bigData)) -
SSR的坑要注意
// 判断是否客户端环境 if (process.client) { const data = localStorage.getItem('data') } -
隐私模式兼容方案
try { localStorage.setItem('test', 'test') } catch (e) { console.warn('隐私模式禁用本地存储') // 降级方案:使用内存存储或cookie }
五、📦 终极解决方案:vuex-persist + 加密
import VuexPersistence from 'vuex-persist'
import SecureLS from 'secure-ls'
const ls = new SecureLS({ isCompression: false })
const vuexLocal = new VuexPersistence({
storage: {
getItem: key => ls.get(key),
setItem: (key, value) => ls.set(key, value),
removeItem: key => ls.remove(key)
},
filter: mutation =>
!mutation.type.includes('敏感操作')
})
const store = new Vuex.Store({
plugins: [vuexLocal.plugin]
})
🎁 资源大礼包
- 完整示例项目:github.com/xiaoyang/vuex-data-rescue
- 性能对比表:
| 方案 | 优点 | 缺点 |
|---|---|---|
| localStorage | 持久化 | 5MB限制 |
| sessionStorage | 标签页级隔离 | 关闭即丢失 |
| IndexedDB | 大容量 | API复杂 |
| Cookies | 自动携带 | 4KB限制 |
⭐ 写在最后
请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.
✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式
✅ 认为我部分代码过于老旧,可以提供新的API或最新语法
✅ 对于文章中部分内容不理解
✅ 解答我文章中一些疑问
✅ 认为某些交互,功能需要优化,发现BUG
✅ 想要添加新功能,对于整体的设计,外观有更好的建议
✅ 一起探讨技术加qq交流群:906392632
最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!