Vuex数据总丢?三招教你永久保存!

235 阅读3分钟

大家好,我是小杨,一个经历过Vuex数据"人间蒸发"惨案的老司机。上周还在加班赶工,第二天打开项目发现购物车空了?用户登录状态丢了?别急!今天就用冰箱存食物的比喻,教你守住Vuex里的每一份数据!

(文末附赠【防丢代码套餐】,直接复制就能用~)


一、❄️ 数据丢失的五大案发现场

案发现场1:页面刷新 → 冰箱断电

// store里的数据就像断电后的冰箱
state: {
  cartItems: []  // 刷新后:空!💔
}

案发现场2:浏览器隐身模式 → 冰箱没插电

// 本地存储无法使用
localStorage.getItem('user') // 返回null

案发现场3:用户手动清除缓存 → 熊孩子清空冰箱

example.com/clear-cache…

案发现场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))
    }
  })
}

四、🚨 小杨的避坑指南

  1. 敏感信息别乱存

    • ❌ 把用户密码存在localStorage
    • ✅ 只存token,及时过期
  2. 大体积数据要谨慎

    // 超过5MB可能引发性能问题
    localStorage.setItem('hugeData', JSON.stringify(bigData))
    
  3. SSR的坑要注意

    // 判断是否客户端环境
    if (process.client) {
      const data = localStorage.getItem('data')
    }
    
  4. 隐私模式兼容方案

    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]
})

🎁 资源大礼包

  1. 完整示例项目:github.com/xiaoyang/vuex-data-rescue
  2. 性能对比表
方案优点缺点
localStorage持久化5MB限制
sessionStorage标签页级隔离关闭即丢失
IndexedDB大容量API复杂
Cookies自动携带4KB限制

⭐  写在最后

请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.

✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式

✅ 认为我部分代码过于老旧,可以提供新的API或最新语法

✅ 对于文章中部分内容不理解

✅ 解答我文章中一些疑问

✅ 认为某些交互,功能需要优化,发现BUG

✅ 想要添加新功能,对于整体的设计,外观有更好的建议

✅ 一起探讨技术加qq交流群:906392632

最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!