vuex persistedstate 是干啥的?
在 Vue 项目里用 Vuex 管理状态时,有没有碰到过「页面一刷新,状态全丢了」的情况?vuex - persistedstate 就是专门解决这个痛点的工具库,它能把 Vuex 的状态持久化存储到 localStorage、sessionStorage 这些地方,刷新页面后状态还能回来,下面通过问答形式,把它的作用、用法、常见问题一次性讲清楚~
Vuex 本身是内存中的状态管理,页面刷新时内存数据会被清空,所以刷新后状态就没了,vuex - persistedstate 的核心作用,是把 Vuex 的 state 自动同步到持久化存储(localStorage),刷新后再从存储里把状态读回来,让状态「跨页面刷新存活」,举个例子:用户登录后存了 token 在 Vuex,刷新页面后 token 还在,不用重新登录,这就是它的功劳~
为啥非要用 vuex - persistedstate?手动存 localStorage 不行吗?
手动存不是不行,但麻烦还容易出错,比如每次触发 mutation 后,都要手动写 localStorage.setItem('xxx', JSON.stringify(state.xxx)),要是有很多状态要存,代码会很冗余,而且手动处理容易漏掉某些 mutation,导致状态和存储不同步,vuex - persistedstate 是自动监听 Vuex 的 mutation,每次状态变化后自动更新持久化存储;刷新时又自动把存储里的数据恢复到 Vuex,全程不用你写重复的存储逻辑,省心又稳定~
vuex - persistedstate 具体怎么用?从安装到进阶
1 第一步:安装依赖
用 npm 或者 yarn 装包就行,打开终端,执行:npm install vuex - persistedstate --save
或者
yarn add vuex - persistedstate
装完后,就能在 Vuex 的 store 里配置啦~
2 基本配置:让状态持久化
假设你已经有 Vuex 的 store 结构,现在要引入 persistedstate,代码大概长这样: ```js // 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: { ... }, mutations: { ... }, actions: { ... }, plugins: [createPersistedState()] // 关键:把插件加入plugins数组 })
export default store
这样配置后,Vuex 的整个 state 会被存到 localStorage(默认存储方式),刷新页面时会自动恢复~ <h3>3.3 进阶:自定义存储规则(存哪里、存哪些)</h3> 默认存 localStorage,如果你想改存储方式(比如存 sessionStorage,关闭标签页就清空),或者只存部分状态,需要配置参数: - **例子1:改存储到 sessionStorage** ```js plugins: [ createPersistedState({ storage: window.sessionStorage // 指定存储引擎 }) ]
例子2:只存部分模块/状态(paths配置)假设 state 里有 user(用户信息)和 cart(购物车)两个模块,只想存 user 的 token 和 cart 的商品列表:
plugins: [ createPersistedState({ paths: ['user.token', 'cart.items'] // 数组里写要存的状态路径 }) ]
例子3:自定义存储逻辑(比如用 cookie)如果想把状态存到 cookie(需要结合 cookie 库,js - cookie):
import Cookies from 'js - cookie'
plugins: [ createPersistedState({ storage: { getItem: key => Cookies.get(key), setItem: (key, value) => Cookies.set(key, value, { expires: 7 }), // 存7天 removeItem: key => Cookies.remove(key) } }) ]
这样就能灵活控制状态存哪里、存多少、怎么存~ <h2>四、用的时候容易踩坑?这些问题帮你避坑</h2> <h3>4.1 问题:和直接用 localStorage 手动存,有啥本质区别?</h3> 手动存是「你主动去存」,而 vuex - persistedstate 是「自动监听状态变化后存」,比如你在 mutation 里改了状态,插件会自动触发存储,不用你在每个 mutation 里写 localStorage 代码,而且恢复状态时,插件会在 store 初始化时自动把存储的数据读回来,不用你手动写读取逻辑,简单说,它把「状态和存储同步」的过程自动化了,减少重复代码和出错概率~ <h3>4.2 问题:多模块状态咋精准存储?</h3> 当 Vuex 分了很多模块(modules),想只存某几个模块的状态,用 paths 配置就行,比如模块结构是: ```js const store = new Vuex.Store({ modules: { user: { state: { token: '', name: '' }, ... }, cart: { state: { items: [], count: 0 }, ... } } })
如果只想存 user 的 token 和 cart 的 items,配置 paths: ['user.token', 'cart.items']
,注意路径要写对,模块名 + 状态字段,多层嵌套也一样('user.info.phone')~
3 问题:想加密存储的数据,咋做?
因为 localStorage 存的是明文,敏感数据(token、用户信息)直接存不安全,可以结合加密库(crypto - js),在存储前加密,读取后解密,做法是用插件的 serialize 和 deserialize 方法: ```js import { createPersistedState } from 'vuex - persistedstate' import CryptoJS from 'crypto - js'
const SECRET_KEY = '你自己的密钥'
const encryptedState = createPersistedState({ serialize: (state) => { // 把state加密后转成字符串 return CryptoJS.AES.encrypt(JSON.stringify(state), SECRET_KEY).toString() }, deserialize: (str) => { // 解密后转成对象 const bytes = CryptoJS.AES.decrypt(str, SECRET_KEY) return JSON.parse(bytes.toString(CryptoJS.enc.Utf8)) } })
然后把 encryptedState 加到 plugins 里,这样存到 localStorage 的就是加密后的字符串,读取时自动解密~ <h3>4.4 问题:旧浏览器不支持 localStorage,咋处理?</h3> 有些老浏览器(IE 低版本)可能不支持 localStorage,这时候插件会报错,可以做兼容:要么检测浏览器是否支持,不支持就提示用户升级;要么配置 fallback 存储方式,比如用 cookie 作为 fallback(需要结合 cookie 库),或者自己实现一个简单的内存存储(但刷新会丢,只适合临时兼容),现在很多项目已经放弃兼容非常古老的浏览器,所以优先考虑用户群体的浏览器版本~ <h3>4.5 问题:状态更新后,存储没同步?</h3> 先检查 plugins 的配置顺序,Vuex 的 plugins 是按数组顺序执行的,如果有其他插件影响了状态,可能导致 persistedstate 没及时捕获,确认 mutation 里是正确修改了 state(比如用 Vuex 的规范,mutation 里直接改 state,不要异步操作),如果是异步修改状态(比如在 action 里改),要确保 action 里提交了 mutation,因为插件只监听 mutation 的提交,要是还不行,试试把 paths 配置得更明确,缩小存储范围,看是否是某些复杂状态导致同步失败~ <p>vuex - persistedstate 算是 Vue 生态里解决「Vuex 状态持久化」的刚需工具,只要你项目里用了 Vuex,又想让状态跨刷新保留,它就能帮你省不少事儿,从安装到自定义配置,再到踩坑解决,核心思路就是「让状态和持久化存储自动同步」,实际项目里根据需求调整存储方式、加密、模块过滤这些细节,就能既灵活又安全地用起来啦~要是你还有其他冷门场景的问题,评论区聊聊?</p>
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。