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 } /** * 打印日志 * @param mutationId * @param mutation * @param state */ function logGroup( mutationId: string, mutation: SubscriptionCallbackMutation, 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, state: StateTree) => { // 记录日志 logger && logGroup(mutation.storeId, mutation, state) const tempKey = `${key}-${mutation.storeId}` setState(tempKey, state, storage) }, { immediate: true, deep: true } ) } // 初始化时获取数据,如果有的话,把原来的pinia的state替换掉 } }