117 lines
2.9 KiB
TypeScript
117 lines
2.9 KiB
TypeScript
import type {
|
||
PiniaPlugin,
|
||
PiniaPluginContext,
|
||
StateTree,
|
||
SubscriptionCallbackMutation
|
||
} from 'pinia'
|
||
|
||
import { Logger } from '@/utils/utils'
|
||
|
||
/**
|
||
* Storage类型
|
||
*/
|
||
export interface Storage {
|
||
getItem: (key: string) => any
|
||
setItem: (key: string, value: any) => void
|
||
removeItem: (key: string) => void
|
||
}
|
||
|
||
/**
|
||
* 配置类型
|
||
*/
|
||
export interface Options {
|
||
/**
|
||
* 存储类型,默认为 `window.localStorage`
|
||
*/
|
||
storage?: Storage
|
||
/**
|
||
* 存储的key值,默认为 `pinia`
|
||
*/
|
||
key?: string
|
||
/**
|
||
* 是否开启日志,默认为 `false`
|
||
*/
|
||
logger?: boolean
|
||
activeStores?: Array<string>
|
||
}
|
||
|
||
/**
|
||
* 打印日志
|
||
* @param mutationId
|
||
* @param mutation
|
||
* @param state
|
||
*/
|
||
function logGroup(
|
||
mutationId: string,
|
||
mutation: SubscriptionCallbackMutation<any>,
|
||
state: StateTree
|
||
) {
|
||
const group = Logger.groupCollapsed || Logger.group
|
||
try {
|
||
group(mutationId, new Date().toLocaleString())
|
||
Logger.log('mutation', mutation)
|
||
Logger.log('state', state)
|
||
Logger.groupEnd()
|
||
} catch (e) {
|
||
Logger.log('—— log end ——')
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @params option
|
||
* @default options = { storage: window.localStorage, key: 'pinia', logger: false }
|
||
*/
|
||
export function StoragePlugin(options?: Options): PiniaPlugin {
|
||
const activeStores = options?.activeStores || []
|
||
|
||
const storage = options?.storage || (window && window.localStorage)
|
||
const key = options?.key || 'pinia'
|
||
const logger = options?.logger || false
|
||
|
||
// 获取state的值
|
||
const getState = (key: string, storage: Options['storage']) => {
|
||
const value = (storage as Storage).getItem(key)
|
||
try {
|
||
return typeof value === 'string'
|
||
? JSON.parse(value)
|
||
: typeof value === 'object'
|
||
? value
|
||
: undefined
|
||
} catch (err) {}
|
||
|
||
return undefined
|
||
}
|
||
|
||
// 设置state的值
|
||
const setState = (key: string, state: StateTree, storage: Options['storage']) => {
|
||
return (storage as Storage).setItem(key, JSON.stringify(state))
|
||
}
|
||
|
||
return (Context: PiniaPluginContext) => {
|
||
const store: PiniaPluginContext['store'] = Context.store
|
||
if (
|
||
(activeStores.length > 0 && activeStores.includes(store.$id)) ||
|
||
activeStores.length === 0
|
||
) {
|
||
const tempKey = `${key}-${store.$id}`
|
||
const data = getState(tempKey, storage)
|
||
data && store.$patch(data)
|
||
|
||
// $subscribe()一个 store的方法来观察 state 和它的变化,类似于 Vuex 的subscribe 方法
|
||
store.$subscribe(
|
||
(mutation: SubscriptionCallbackMutation<any>, state: StateTree) => {
|
||
// 记录日志
|
||
logger && logGroup(mutation.storeId, mutation, state)
|
||
const tempKey = `${key}-${mutation.storeId}`
|
||
setState(tempKey, state, storage)
|
||
},
|
||
{
|
||
immediate: true,
|
||
deep: true
|
||
}
|
||
)
|
||
}
|
||
// 初始化时获取数据,如果有的话,把原来的pinia的state替换掉
|
||
}
|
||
}
|