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

2023-05-16

文章目录

    • 引入
    • 问题演示
    • 实现效果展示、
    • 实现步骤
      • 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];
    }
  }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 一分钟学会Python中pip的安装与使用

    文章目录 一 简单介绍二 下载安装三 最常用命令1 显示版本和路径2 获取帮助3 升级 pip4 安装包5 升级包6 卸载包7 搜索包8 显示安装包信息9 列出已安装的包10 查看指定包的详细信息 一 简单介绍 pip 是 Python 包
  • 史上最全的Android基础教程+实战练习+经验技巧(建议收藏)|寻找C站宝藏

    博主一年前发布了一些Android项目和教程 xff0c 当时就是想分享给大家 xff0c 帮助大家解决遇到的难题 xff0c 少走弯路 经常看到评论下有同学说博主很细心 讲的很详细 xff0c 还有很良心免费分享源码 xff0c 博主很欣
  • Android Studio实现音乐播放器2.0

    项目目录 一 引言二 项目概述1 需求分析2 设计分析3 资源文件分析 三 开发环境四 优化设计 x1f337 1 上一首下一首 x1f33e 2 控件UI优化 x1f341 3 登录和注册 x1f334 4 数据库设计 x1f33b 5
  • Android Studio实现功能强大的购物商城APP

    这里写目录标题 一 项目概述二 开发环境三 项目结构四 配置服务器五 项目演示五 项目总结六 源码获取 一 项目概述 本次项目是现在软件商店很流行的购物商城APP xff0c 现在万物互联的时代 xff0c 网上shopping早已经是大家
  • 教你彻底卸载Ubuntu双系统,去污不残留

    我们卸载Ubuntu双系统 xff0c 可能出于以下原因 xff1a span class token number 1 span span class token class name Ubuntu span 系统内核损坏无法正常进入 s
  • Could not initialize class org.codehaus.groovy.vmplugin.v7.Java7

    Android Studio 2022 2 1同步时出现的报错 xff0c 原因是使用了AS自带的jdk17 xff0c 我们换成自己电脑上安装的jdk1 8即可 xff0c 没有安装的同学看JDK安装教程 1 首先File gt Sett
  • Android Studio实现文艺阅读App

    项目目录 一 系统概述二 系统特点三 开发环境四 运行演示五 源码获取 一 系统概述 本次带来的文艺阅读App可以提供高质量的原创文学作品 用户可以App中找到各种类型的文学作品 xff0c 包括小说 散文 诗歌等 xff0c 由来自不同领
  • Failed to install the following Android SDK packages as some licences have not been accepted. bu

    报错信息 Android 开发者工具 Android开发者构建工具28 0 3 Android开发者平台28的协议都没有被接受 Failed to install the following Android SDK packages as
  • Qt如何使QTreeWidget始终保持展开?

    文章已更新 xff0c 最新地址 xff1a http www fearlazy com index php post 122 html 有时候我们在使用树形控件实现项目分组功能时 xff0c 不希望点击组名 即顶层Item 时收缩 此时应
  • Received status code 400 from server: Bad Request

    一 报错信息 FAILURE span class token operator span span class token class name Build span failed span class token keyword wit
  • wangEditor使用教程

    1 安装 xff08 vue2 xff09 yarn add 64 wangeditor editor 或者 npm install 64 wangeditor editor save yarn add 64 wangeditor edit
  • 微信小程序之问卷调查

    登录界面 login js span class token comment miniprogram pages login login js span span class token function Page span span cl
  • NISP

    文章目录 NISP七月份练习01NISP七月份练习02NISP七月份练习03NISP七月份练习04NISP七月份练习05NISP七月份练习06NISP七月份练习07NISP七月份练习08NISP七月份练习09NISP七月份练习10NISP七
  • Redis系列漏洞总结

    Redis系列漏洞总结 文章目录 Redis系列漏洞总结环境 ubuntu16 04 redis5 0 1 redis下载及安装redis 漏洞利用方式0x01 绝对路径写shell0x02 redis 写入ssh公钥0x03 Redis主
  • 国密浏览器介绍与下载

    国密浏览器介绍与下载 密信浏览器介绍支持操作系统下载地址 奇安信可信浏览器 xff08 国密开发者专版 xff09 介绍支持操作系统下载地址 红莲花安全浏览器介绍支持操作系统下载地址 零信浏览器介绍支持操作系统下载地址 360安全浏览器介绍
  • linux/php一句话图片马及实例

    Ubuntu一句话图片马 准备一张图片tu jpeg phpinfo php和hack php xff1b Phpinfo php文件内容 xff1a hack php文件内容 xff1a 准备一个16进制软件UE UltraEdit li
  • 黑客网络安全扫描工具

    黑客网络安全扫描工具 项目简介1 子域名枚举扫描器或爆破工具2 数据库类漏洞扫描器或爆破工具3 弱口令 弱用户名扫描器或爆破工具4 物联网设备识别工具或扫描器5 反射型或DOM Based XSS扫描器6 企业资产管理或信息泄露搜集工具7
  • MSF之ms17-010永恒之蓝漏洞利用

    MSF之ms17 010永恒之蓝漏洞利用 准备扫描漏洞漏洞攻击 准备 实验准备环境 xff1a 被攻击机 xff1a 虚拟机win7x64位系统 其IP为 xff1a 10 101 2 11 xff08 关闭了防火墙 xff09 攻击机 x
  • linux上安装mysql8.0及常见mysql设置

    1 服务器环境是linux环境 xff0c 使用yum方式安装 yum install mysql server 2 安装完成之后进入目录 etc my cnf 查看文件是否有配置 xff0c 一般都会在 etc my cnf d 文件目录
  • from origin ‘null‘ has been blocked by CORS policy: Cross origin requests are only supported for pro

    Access to script at file C Users dawulei Desktop E9 A1 B9 E7 9B AE E5 9D A6 E5 85 8B E5 A4 A7 E6 88 98 txt htrml js txt

随机推荐