import type { PiniaPluginContext } from 'pinia'; interface CustomObject { [key: string]: { [key: string]: any; }; } export interface StorageApi { getItem: (key: string) => string | null; setItem: (key: string, value: any) => void; removeItem: (key: string) => void; } export interface ReducerOptionsArray { [key: string]: string[] | boolean; } export interface PersistedOptions { stroage?: StorageApi; reducer?: string[] | ReducerOptionsArray; name?: string; } function formateReducer(value: PersistedOptions['reducer'], ctx: PiniaPluginContext): CustomObject { const state = ctx.pinia.state.value; if (!value) return state; const saveState: CustomObject = {}; if (Array.isArray(value)) { value.forEach((moduleName) => { saveState[moduleName] = state[moduleName]; }); } else if (typeof value === 'object' && !Array.isArray(value)) { // 遍历 reducer Object.keys(value).forEach((moduleName) => { // 添加模块 saveState[moduleName] = {}; const moduleValue = value[moduleName]; // 模块值 const stateModule = state[moduleName]; // 状态值 if (typeof moduleValue === 'boolean') { stateModule && (saveState[moduleName] = stateModule); } else if (Array.isArray(moduleValue)) { moduleValue.forEach((item) => { stateModule && (saveState[moduleName][item] = stateModule[item]); }); } }); } return saveState; } /** * 持久化存储 * @param options * @returns */ export function createPersistedState( options?: PersistedOptions, ): (ctx: PiniaPluginContext) => object { // 存储方式 const stroage = options?.stroage || window.localStorage; // 前缀 const name = options?.name || 'vuex-pinia'; function piniaPlugin(ctx: PiniaPluginContext) { // this subscription will be removed after the component is unmounted, so we need need to fill in the second parameter try { ctx.store.$subscribe(() => { const sv = JSON.parse(stroage.getItem(name) as string) || {}; const reducer = formateReducer(options?.reducer, ctx); stroage.setItem(name, JSON.stringify(Object.assign(sv, reducer))); }, true); console.log(ctx); const rv = JSON.parse(stroage.getItem(name) as string); return rv && rv[ctx.store.$id]; } catch (error) { console.log(error); } } return piniaPlugin; }