index.ts 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import type { PiniaPluginContext } from 'pinia';
  2. interface CustomObject {
  3. [key: string]: {
  4. [key: string]: any;
  5. };
  6. }
  7. export interface StorageApi {
  8. getItem: (key: string) => string | null;
  9. setItem: (key: string, value: any) => void;
  10. removeItem: (key: string) => void;
  11. }
  12. export interface ReducerOptionsArray {
  13. [key: string]: string[] | boolean;
  14. }
  15. export interface PersistedOptions {
  16. stroage?: StorageApi;
  17. reducer?: string[] | ReducerOptionsArray;
  18. name?: string;
  19. }
  20. function formateReducer(value: PersistedOptions['reducer'], ctx: PiniaPluginContext): CustomObject {
  21. const state = ctx.pinia.state.value;
  22. if (!value) return state;
  23. const saveState: CustomObject = {};
  24. if (Array.isArray(value)) {
  25. value.forEach((moduleName) => {
  26. saveState[moduleName] = state[moduleName];
  27. });
  28. } else if (typeof value === 'object' && !Array.isArray(value)) {
  29. // 遍历 reducer
  30. Object.keys(value).forEach((moduleName) => {
  31. // 添加模块
  32. saveState[moduleName] = {};
  33. const moduleValue = value[moduleName]; // 模块值
  34. const stateModule = state[moduleName]; // 状态值
  35. if (typeof moduleValue === 'boolean') {
  36. stateModule && (saveState[moduleName] = stateModule);
  37. } else if (Array.isArray(moduleValue)) {
  38. moduleValue.forEach((item) => {
  39. stateModule && (saveState[moduleName][item] = stateModule[item]);
  40. });
  41. }
  42. });
  43. }
  44. return saveState;
  45. }
  46. /**
  47. * 持久化存储
  48. * @param options
  49. * @returns
  50. */
  51. export function createPersistedState(
  52. options?: PersistedOptions,
  53. ): (ctx: PiniaPluginContext) => object {
  54. // 存储方式
  55. const stroage = options?.stroage || window.localStorage;
  56. // 前缀
  57. const name = options?.name || 'vuex-pinia';
  58. function piniaPlugin(ctx: PiniaPluginContext) {
  59. // this subscription will be removed after the component is unmounted, so we need need to fill in the second parameter
  60. try {
  61. ctx.store.$subscribe(() => {
  62. const sv = JSON.parse(stroage.getItem(name) as string) || {};
  63. const reducer = formateReducer(options?.reducer, ctx);
  64. stroage.setItem(name, JSON.stringify(Object.assign(sv, reducer)));
  65. }, true);
  66. console.log(ctx);
  67. const rv = JSON.parse(stroage.getItem(name) as string);
  68. return rv && rv[ctx.store.$id];
  69. } catch (error) {
  70. console.log(error);
  71. }
  72. }
  73. return piniaPlugin;
  74. }