electron+vue3全家桶+vite项目搭建【16.1】electron多窗口,pinia状态同步,扩展store方法,主动同步pinia的状态【推荐】

这篇具有很好参考价值的文章主要介绍了electron+vue3全家桶+vite项目搭建【16.1】electron多窗口,pinia状态同步,扩展store方法,主动同步pinia的状态【推荐】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

引入

demo项目地址

我们之前写了一个自动同步pinia状态的插件,可以参考如下文章

electron+vue3全家桶+vite项目搭建【16】electron多窗口,pinia状态无法同步更新问题解决

这里面有一个较大的弊端,就是pinia中的store,只要其中的某个属性修改,就会触发这个store的全量更新,当我们有一些状态频繁更新的时候,就会影响性能,并且有些窗口中的store其实是不需要同步的,但我们无法进行精准的控制,而且为了保证多个窗口间的同步一致,我们做了很多兜底处理。

现在提供另一个思路,我们不被动的自动更新同步store的状态,而是通过扩展store的actions方法,让业务主动调用方法时来主动通知其他窗口完成同步。

实现效果如下

可以看到,只有当我主动触发同步方法时,才会进行窗口间的状态同步

electron+vue3全家桶+vite项目搭建【16.1】electron多窗口,pinia状态同步,扩展store方法,主动同步pinia的状态【推荐】,electron+vue3全家桶,electron,javascript,前端,pinia,vue3全家桶

实现步骤

1.自定义pinia插件

自定义pinia插件,扩展store,扩展一个stateSync方法

  • 我们先声明一个stateSync方法,然后在store初始化的时候重写该方法

  • src\store\plugins\shareStoreByActionPlugin.ts

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

// 设置本地store缓存的key
const STORE_CACHE_KEY_PREFIX = "store_";

declare module "pinia" {
  export interface PiniaCustomProperties {
    // 通知主进程让所有窗口同步pinia的状态
    stateSync(): void;
  }
}

// 处理electron多窗口,pinia共享问题
export function shareStorePlugin({ store }: PiniaPluginContext) {
  // 初始化本地缓存版本
  const storeName: string = store.$id;
  // 初始化store
  initStore(store);
  // 重写状态同步方法
  store.stateSync = () => {
    updateStoreSync(stringify(store.$state), storeName);
  };

  // 监听数据同步修改
  ipcRenderer.on(
    "pinia-store-set",
    (event, targetStoreName: string, jsonStr: string) => {
      console.log("被动更新哦");
      // 监听到状态改变后,同步更新状态
      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++) {
          changeState(store.$state, keys[i], values[i]);
        }
      }
    }
  );
}

/**
 * 状态更新同步
 * @param stateJsonStr 序列化的状态修改字符串
 * @param storeName  修改的状态的名称
 */
function updateStoreSync(stateJsonStr: string, storeName: string) {
  // 通知主线程更新
  ipcRenderer.invoke("pinia-store-change", storeName, stateJsonStr);

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

/**
 * 修改state的值
 * 补充 如果反序列化的字段是map类型,需要额外处理
 */
function changeState(state: any, key: any, value: any) {
  if (state[key] instanceof Map) {
    if (value instanceof Array) {
      state[key] = new Map(value);
    } else {
      state[key] = new Map(Object.entries(value as object));
    }
  } else {
    state[key] = value;
  }
}

/**
 * 初始化状态对象
 * @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++) {
      changeState(store.$state, keys[i], values[i]);
    }
  }
}

/**
 * 2023/07/03 自定义序列化方式, 处理ts中map类型/对象序列化后为 {} 的情况
 */
function stringify(obj: any): string {
  return JSON.stringify(cloneToObject(obj));
}

// 将字段包含map的对象转为json对象的格式
function cloneToObject(obj: any): any {
  let newObj: any = obj;
  if (obj instanceof Map) {
    return Object.fromEntries(obj);
  }
  if (obj instanceof Object) {
    newObj = {};
    const keys = Object.keys(obj);
    const values = Object.values(obj);
    for (let i = 0; i < keys.length; i++) {
      const key = keys[i];
      const value = values[i];
      newObj[key] = cloneToObject(value);
    }
  }
  if (obj instanceof Array) {
    newObj = [];
    for (let i = 0; i < obj.length; i++) {
      newObj[i] = cloneToObject(obj[i]);
    }
  }
  return newObj;
}

然后我们主动在pinia的初始化中使用插件文章来源地址https://www.toymoban.com/news/detail-678190.html

  • src\store\index.ts
import { createPinia } from "pinia";
// import { shareStorePlugin } from "./plugins/shareStorePlugin";
import { shareStorePlugin } from "./plugins/shareStoreByActionPlugin";

const pinia = createPinia();

// 添加状态共享插件
pinia.use(shareStorePlugin);

export default pinia;

2.主进程补充同步处理

  • electron\main\index.ts
  • 主进程中添加pinia监听,遍历通知窗口进行pinia的更新
/**pinia多窗口共享 */
ipcMain.handle(
  "pinia-store-change",
  (
    event,
    storeName: string,
    jsonStr: string,
  ) => {
    // 遍历window执行
    for (const currentWin of BrowserWindow.getAllWindows()) {
      const webContentsId = currentWin.webContents.id;
      if (webContentsId !== event.sender.id && !currentWin.isDestroyed()) {
        currentWin.webContents.send(
          "pinia-store-set",
          storeName,
          jsonStr
        );
      }
    }
  }
);

到了这里,关于electron+vue3全家桶+vite项目搭建【16.1】electron多窗口,pinia状态同步,扩展store方法,主动同步pinia的状态【推荐】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • electron+vue3全家桶+vite项目搭建【13.1】ipc通信的使用,主进程与渲染进程之间的交互

    electron项目常常由一个主进程和多个渲染进程构成,渲染进程之间是隔离的,而所有渲染进程都和主进程共享资源。 所有的渲染进程都是由主进程创建的 每个窗口都对应着一个渲染进程 所有的渲染进程共享一个主进程 我们主进程与渲染进程交互,渲染进程与渲染进程交互【

    2024年02月10日
    浏览(61)
  • 基于electron25+vite4创建多窗口|vue3+electron25新开模态窗体

    在写这篇文章的时候,查看了下electron最新稳定版本由几天前24.4.0升级到了25了,不得不说electron团队迭代速度之快! 前几天有分享一篇electron24整合vite4全家桶技术构建桌面端vue3应用示例程序。 https://www.cnblogs.com/xiaoyan2017/p/17436076.html 这次继续接着上次项目,主要介绍electron

    2024年02月06日
    浏览(81)
  • 基于Electron24+Vite4+Vue3搭建桌面端应用

    一说到创建桌面应用,就不得不提及Electron和Tauri框架。这次给大家主要分享的是基于electron最新版本整合vite4.x构建vue3桌面端应用程序。 之前也有使用vite2+vue3+electronc创建桌面端项目,不过  vue-cli-plugin-electron-builder  脚手架插件构建的项目electron版本只有13.x。如今electron版本

    2024年02月06日
    浏览(71)
  • 现有的vue3+ts+vite项目集成electron

    Electron是使用JavaScript,HTML和CSS构建跨平台的桌面应用程序框架。 Electron兼容Mac、Windows和Linux,可以构建出三个平台的应用程序。 安装依赖 原来有一个vue3+ts+vite+pnpm的项目,其中sub-modules是子项目,web是主入口项目,项目结构如下: 需要将其转换成Electron项目,只需要在原来

    2024年02月12日
    浏览(67)
  • 快速搭建Electron+Vite3+Vue3+TypeScript5脚手架 (无需梯子,快速安装Electron)

    Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 Chromium 和 Node.js 到 二进制的 Electron 允许您保持一个 JavaScript 代码代码库并创建 在Windows上运行的跨平台应用 macOS和Linux——不需要本地开发经验(这段话是来自官网)。 根据vite官网文档 项目创建完成后进

    2024年02月02日
    浏览(103)
  • 使用vue3+vite+elctron构建小项目介绍Electron进程间通信

    进程间通信 (IPC) 是在 Electron 中构建功能丰富的桌面应用程序的关键部分之一。 由于主进程和渲染器进程在 Electron 的进程模型具有不同的职责,因此 IPC 是执行许多常见任务的唯一方法,例如从 UI 调用原生 API 或从原生菜单触发 Web 内容的更改。 在 Electron 中,进程使用 ipcM

    2024年02月06日
    浏览(62)
  • vite+ vue3(现有项目或者新项目)+electron打包教程,以及electron代码热重载页面(保姆级教程),一文带你走完全过程

      1.删掉type这个字段,不然会报错  2.然后加上\\\"main\\\": \\\"electron/main.js\\\",  3.在scripts字段中加入启动electron的命令:如下图 5.这时候你去打开控制台输入输入npm run start会得到一片空白,展示如下页面 1.因为现在监听的是vue打包后的dist文件夹中的index.html 2.我就不教你们怎么打开那个

    2024年02月11日
    浏览(121)
  • Vue3+Vite项目搭建

    技术栈:vue3+ts+vite+vue-router+element-plus+pinia 为什么选择vite而不是vue-cli: vite 是一个基于 Vue3 单文件组件的非打包开发服务器,它做到了本地快速开发启动: 快速的冷启动,不需要等待打包操作; 即时的热模块更新,替换性能和模块数量的解耦让更新飞起; 真正的按需编译,

    2024年02月08日
    浏览(48)
  • vite搭建vue3项目

    参考视频 创建一个项目名称的文件夹 执行命令:npm init -y 快速的创建一个默认的包信息 安装vite: npm i vite -D -D开发环境的依赖 安装vue,现在默认是vue3. 执行命令: npm i vue -D/-S都可以 创建index.html文件,src=“入口js文件” ,添加id=\\\"app\\\"挂载点 创建src目录下的js入口文件main.js 创建

    2024年02月09日
    浏览(47)
  • Vue3 + Vite 实现项目搭建

    首先嘞,这个博文就是简单的记录一下自己的对 Vue3 的学习,所以说呢,并不代表他是完全正确的。 创建 Vue3 项目有两种常见的方式,一种是想 vue2 版本一样使用脚手架工具创建,创建 vue3 项目的脚手架必须是4版本以上的,另一种方法就是使用 vite 创建,为什么使用 vite 呢

    2024年02月11日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包