需求
在使用vuex时,经常会遇到需要数据持久化的需求,比如用户的token、用户的个人信息等,这些数据在登录成功后,需要持久化到本地,以便下次登录时使用。
实现
vuex Plugin
这里使用vuex的插件作为实现, 实现的内容有:
- 当store初始化时,获取本地存储的数据,并设置到store中
- 每次store提交mutation时,将store中指定的数据持久化到本地
用到的第三方库
- shvl:获取和设置对象内的点标记属性
- deepmerge:深度合并两个或多个对象的可枚举属性。
具体实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| import { Store } from 'vuex' import * as shvl from 'shvl' import merge from 'deepmerge'
interface Storage { getItem: (key: string) => any setItem: (key: string, value: any) => void removeItem: (key: string) => void }
interface Options { key?: string paths: string[] storage: Storage arrayMerger?: (state: any[], saved: any[]) => any }
const createPersistedState = <State = any>(options: Options) => { const key = 'vuex' options = options ?? {}
//从storage中获取数据 function getState(key: string, storage: Storage) { const value = storage.getItem(key) ?? {}
try { return typeof value === 'string' ? JSON.parse(value) : typeof value === 'object' ? value : {} } catch (err) { console.error(err) }
return {} }
//将stroage中的数据合并到state中 function patchState(store: Store<State>, storage: Storage) { const storeState = getState(key, storage) console.log(storeState)
store.replaceState( merge(store.state, storeState, { arrayMerge: options.arrayMerger || function (store, saved) { return saved }, clone: false }) ) }
//将state中的数据保存到stroage中 function setState(key: string, state: any, storage: Storage) { return storage.setItem(key, JSON.stringify(state)) }
/** * 给定一个路径数组及状态,返回一个对象并按照路径设置值 * @param state:状态 * @param paths:路径数组 * @returns */ function reducer(state: any, paths: string[]) { return Array.isArray(paths) ? paths.reduce(function (substate, path) { return shvl.set(substate, path, shvl.get(state, path)) }, {}) : state }
//返回plugin函数 return (store: Store<any>) => { //首先将stroage中的数据合并到state中 patchState(store, options.storage)
//然后监听state的变化,并将需要保存的数据保存到stroage中 store.subscribe((mutation, state) => { setState(key, reducer(state, options.paths), options.storage) }) } }
export default createPersistedState
|
使用
导入插件,并在vuex的plugins中注册,将需要持久化的数据路径指定到paths中,并将stroage指定为本地存储,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import { createStore } from 'vuex' import createPersistedState from 'persistedstate' export default createStore<any>({ state: () => { return { name: 'store', } }, getters: {}, mutations: {}, actions: {}, modules: { loginModule }, plugins: [ createPersistedState({ paths: ['loginModule.userInfo', 'loginModule.token'], storage: window.localStorage }) ] })
|