什么是 Pinia ?
Pinia
是2019年由vue.js官方成员重新设计的新一代状态管理库,类似Vuex。这里就不过多介绍,具体Pinia使用方法可以参考 Pinia 主页。
下面我们一起研究一下基于Pinia开发的持久化存储插件
什么是持久化存储?
简单的说就是浏览器缓存与Store之间相互同步;我们在使用常规的Store存储的时候,会遇到刷新页面状态库就会被重置,这让我们很苦恼;
通常遇到这个问题,我们很容易想到用sessionStorage
或者localStorage
来存储相应的数据,当存储store变多时,就麻烦了,需要写一堆的废代码,不好阅读也不美观。
有没有更好的办法呢?
pinia-plugin-persist 就很好的解决的这个问题; 但在实际使用中,发现一个不方便的地方,该插件是以模块来存储的,一个store就是一模块,有时候我们需要一个一个字段去存,比如登录我们就只需要存个userInfo字段就行;为了处理类似这种情况在pinia-plugin-persist基础上进行了升级改造。
相关源码
index.d.ts
js
interface PersistStrategy {
key?: string
storage?: Storage
paths?: string[]
}
interface PersistOptions {
enabled: true
strategies?: PersistStrategy[]
}
declare module 'pinia' {
interface DefineStoreOptionsBase<S, Store> {
persist?: PersistOptions
}
}
export { PersistOptions, PersistStrategy }
pinia-store-persist.ts
js
import { PiniaPluginContext } from 'pinia'
import { PersistStrategy } from '../pinia-persist'
type Store = PiniaPluginContext['store']
type PartialState = Partial<Store['$state']>
// 更新本地缓存
export const updateStorage = (strategy: PersistStrategy, store: Store) => {
const storage = strategy?.storage || sessionStorage
const paths = strategy?.paths || []
if (strategy.key) {
// 判断是否按照模块缓存
const state = paths.reduce((obj, key) => {
obj[key] = store.$state[key]
return obj
}, {} as PartialState)
storage.setItem(strategy.key, JSON.stringify(state))
} else {
// 单个缓存
paths.forEach((key) => {
const state = store.$state[key]
storage.setItem(key, JSON.stringify(state))
})
}
}
export default ({ options, store }: PiniaPluginContext): void => {
// 判断插件功能是否开启
if (options.persist?.enabled) {
// 默认策略实例
const defaultStrategy = [
{
key: store.$id,
storage: sessionStorage,
paths: []
}
]
const strategies = options.persist?.strategies?.length ? options.persist?.strategies : defaultStrategy
strategies.forEach((strategy) => {
const storage = strategy?.storage || sessionStorage
const paths = strategy?.paths || []
if (strategy.key) {
const result = storage.getItem(strategy.key)
result && store.$patch(JSON.parse(result))
} else {
paths.forEach((key) => {
const result = storage.getItem(key)
if (result) {
const obj: { [key: string]: any } = {}
obj[key] = JSON.parse(result)
// 同步更新store数据
store.$patch(obj)
}
})
}
})
// 监听state变化,同步更新storage
store.$subscribe(() => {
strategies.forEach((strategy) => {
updateStorage(strategy, store)
})
})
}
}
引入
store/index.ts
js
import { createPinia } from 'pinia'
import piniaStorePersist from '@/plugins/pinia-persist/pinia-store-persist'
const store = createPinia().use(piniaStorePersist)
export default store
使用
js
export const CommonStore = defineStore('common', {
//...
persist: {
enabled: true,
strategies: [
{
storage: localStorage,
paths: ['userInfo']
}
]
}
})
最后
如果本文对您有什么帮助,别忘了动动手指点个赞❤️。 本文如果有错误和不足之处,欢迎大家在评论区指出,多多提出您宝贵的意见!