electron+vue3全家桶+vite项目搭建【17】pinia状态持久化

文章目录

    • 引入
    • 问题演示
    • 实现效果展示、
    • 实现步骤
      • 1.封装状态初始化函数
      • 2.封装状态更新同步函数
      • 3.完整代码

引入

上一篇文章我们已经实现了electron多窗口中,pinia的状态同步,但你会发现,如果我们在一个窗口里面修改了状态,然后再打开另一个窗口,此时窗口的状态并没有同步,所以我们需要对pinia的状态进行持久化处理,并在页面初始化时取到本地缓存的状态。

demo项目地址

问题演示

如下所示,我们先在一个窗口中自增数值,然后再打开另一个窗口,此时窗口中的数值仍然是初始值,只有我们再次点击增加时,才会同步【因为我们上一节实现了pinia多窗口状态同步】

实现效果展示、

实现步骤

1.封装状态初始化函数

我们在src\store\plugins\shareStorePlugin.ts中补充初始化函数

  • 当pinia对应的状态对象初始化时,我们将对象的引用传入
  • 从本地缓存中取到序列化的store对象,我们将其反序列化后遍历key、value设置store的状态即可
/**
 * 初始化状态对象
 * @param store
 */
function initStore(store: any) {
  const cacheKey = STORE_CACHE_KEY_PREFIX + store.$id;
  // 从本地缓存中读取store的值
  const stateJsonStr = cacheUtils.get(cacheKey);
  if (stateJsonStr) {
    const stateCache = JSON.parse(stateJsonStr);
    const keys = Object.keys(stateCache);
    const values = Object.values(stateCache);

    /// 更新各个key对应的值的状态
    for (let i = 0; i < keys.length; i++) {
      store.$state[keys[i]] = values[i];
    }
  }
}

2.封装状态更新同步函数

我们在src\store\plugins\shareStorePlugin.ts中补充状态更新同步逻辑

  • 之前的主动更新逻辑都是累加版本号、设置缓存,通知更新,我们不妨将这段逻辑抽离
  • 将对应的store序列化后存入本地缓存中
/**
 * 状态更新同步
 * @param stateJsonStr 序列化的状态修改字符串
 * @param storeName  修改的状态的名称
 * @param storeUpdateVersion  状态修改的版本号
 */
function updateStoreSync(
  stateJsonStr: string,
  storeName: string,
  storeUpdateVersion: number
) {
  // 更新本地缓存的store版本号
  const storeCacheVersionKey = STORE_CACHE_VERSION_KEY_PREFIX + storeName;
  cacheUtils.set(storeCacheVersionKey, storeUpdateVersion, STORE_CACHE_TIME);

  // 通知主线程更新
  ipcRenderer.invoke('pinia-store-change', storeName, stateJsonStr);

  // 更新本地缓存的store
  cacheUtils.set(STORE_CACHE_KEY_PREFIX + storeName, stateJsonStr);
}

3.完整代码

我们调整之前的代码,将两个函数嵌入到原来的逻辑之中

src\store\plugins\shareStorePlugin.ts

import { ipcRenderer } from "electron";
import cacheUtils from "@/utils/cacheUtils";
import { PiniaPluginContext } from "pinia";

// 预设本地store版本缓存时间为50s  实际开发中可以设置很大,缓存时间的限制,目的是为了让版本归零,避免自增超过上限
const STORE_CACHE_TIME = 50;
// 设置本地store缓存的key
const STORE_CACHE_KEY_PREFIX = "store_";
const STORE_CACHE_VERSION_KEY_PREFIX = STORE_CACHE_KEY_PREFIX + "version_";

declare module "pinia" {
  export interface PiniaCustomProperties {
    storeUpdateVersion: number; // 标记store变更的版本
  }
}

/**获取本地缓存的store的修改版本 */
function getLocalStoreUpdateVersion(storeCacheKey: string) {
  let currentStoreUpdateVersion: number = cacheUtils.get(storeCacheKey);
  // 如果本地没有,就初始化一个
  if (
    currentStoreUpdateVersion === null ||
    currentStoreUpdateVersion === undefined
  ) {
    currentStoreUpdateVersion = 0;
    cacheUtils.set(storeCacheKey, currentStoreUpdateVersion, STORE_CACHE_TIME);
  }
  return currentStoreUpdateVersion;
}

// 处理electron多窗口,pinia共享问题
export function shareStorePlugin({ store }: PiniaPluginContext) {
  // 初始化本地缓存版本
  const storeName: string = store.$id;
  /// 缓存key
  const storeCacheVersionKey = STORE_CACHE_VERSION_KEY_PREFIX + storeName;
  let currentStoreUpdateVersion: number =
    getLocalStoreUpdateVersion(storeCacheVersionKey);
  // 初始化同步store版本
  store.storeUpdateVersion = currentStoreUpdateVersion;

  // 初始化store
  initStore(store);

  // 监听数据变化
  store.$subscribe(() => {
    // 获取本地存储的最新状态
    currentStoreUpdateVersion = cacheUtils.get(storeCacheVersionKey);
    /// 如果本地缓存过期,则重置一个缓存,并且通知主进程让其他窗口更新状态
    if (
      currentStoreUpdateVersion === null ||
      currentStoreUpdateVersion === undefined
    ) {
      currentStoreUpdateVersion = 0;
      store.storeUpdateVersion = currentStoreUpdateVersion;
      console.log(`主动更新 ${storeName} 的状态`);

      // 主动更新
      updateStoreSync(
        JSON.stringify(store.$state),
        storeName,
        store.storeUpdateVersion
      );
    } else {
      // 如果版本一致,则增加版本号,且更新本地存储版本 ,并且通知主线程告知其他窗口同步更新store状态
      if (store.storeUpdateVersion === currentStoreUpdateVersion) {
        store.storeUpdateVersion++;
        console.log(`主动更新 ${storeName} 的状态`);

        // 主动更新
        updateStoreSync(
          JSON.stringify(store.$state),
          storeName,
          store.storeUpdateVersion
        );
      } else {
        // 如果当前store的版本大于本地存储的版本,说明本地版本重置了【过期重新创建】,此时重置store的版本
        // 如果当前store的版本小于本地存储的版本,说明是被动更新引起的state变动回调,此时仅更新版本即可
        store.storeUpdateVersion = currentStoreUpdateVersion;
      }
    }
  });

  // 监听数据同步修改
  ipcRenderer.on(
    "pinia-store-set",
    (event, targetStoreName: string, jsonStr: string) => {
      // 监听到状态改变后,同步更新状态
      if (storeName === targetStoreName) {
        console.log("被动更新状态:" + storeName);

        const obj = JSON.parse(jsonStr);
        const keys = Object.keys(obj);
        const values = Object.values(obj);

        /// 更新各个key对应的值的状态
        for (let i = 0; i < keys.length; i++) {
          store.$state[keys[i]] = values[i];
        }
      }
    }
  );
}

/**
 * 状态更新同步
 * @param stateJsonStr 序列化的状态修改字符串
 * @param storeName  修改的状态的名称
 * @param storeUpdateVersion  状态修改的版本号
 */
function updateStoreSync(
  stateJsonStr: string,
  storeName: string,
  storeUpdateVersion: number
) {
  // 更新本地缓存的store版本号
  const storeCacheVersionKey = STORE_CACHE_VERSION_KEY_PREFIX + storeName;
  cacheUtils.set(storeCacheVersionKey, storeUpdateVersion, STORE_CACHE_TIME);

  // 通知主线程更新
  ipcRenderer.invoke("pinia-store-change", storeName, stateJsonStr);

  // 更新本地缓存的store
  cacheUtils.set(STORE_CACHE_KEY_PREFIX + storeName, stateJsonStr);
}

/**
 * 初始化状态对象
 * @param store
 */
function initStore(store: any) {
  const cacheKey = STORE_CACHE_KEY_PREFIX + store.$id;
  // 从本地缓存中读取store的值
  const stateJsonStr = cacheUtils.get(cacheKey);
  if (stateJsonStr) {
    const stateCache = JSON.parse(stateJsonStr);
    const keys = Object.keys(stateCache);
    const values = Object.values(stateCache);

    /// 更新各个key对应的值的状态
    for (let i = 0; i < keys.length; i++) {
      store.$state[keys[i]] = values[i];
    }
  }
}

你可能感兴趣的:(electron,vue3全家桶,pinia持久化,持久化,pinia)