Electron V28主进程与渲染进程互相通信总结
本文示例采用Electron+Vue3+TS编写,请读者理顺思路,自行带入自己的项目。
注: 读本文前请先搞懂什么是主进程,什么是渲染进程。
在Electron中有着ipcMain
和ipcRenderer、contextBridge
模块,以及创建窗口对象上的webContents
。很显然ipcMain和窗口对象上的webContents是在主进程中使用的,ipcRenderer和contextBridge(用于向渲染进程暴露API)是在预加载脚本中使用的。
请看下方示例,关键讲解写在代码注释中。
一、主进程发送消息到渲染进程
主进程中发送消息,是使用new 窗口时的对象上的webContents发送消息。例如:
main.js中
let appWindow;
const createWindow = () => {appWindow = new BrowserWindow({width: 850,height: 700,webPreferences: {preload: path.join(path.resolve(), 'preload/index.js')}})// 创建窗口后,向渲染进程发送平台信息,但是不能直接发送给渲染进程,需要通过预加载脚本进行中转appWindow.webContents.send('platform', process.platform)
}
于是在preload/index.js中:
const { contextBridge, ipcRenderer } = require('electron')
// ipcRenderer监听消息名为platform的事件,并在第二个参数回调函数中接收参数
// 回调函数又包含两个参数,一个是事件信息,一个是消息传递的参数
ipcRenderer.on('platform', (_, arg) => {// 拿到参数后,我们使用contextBridge向渲染进程中(也就是html或vue界面)暴露名为platform的API,当然名字可自定义其它。// 暴露出的API挂载在window对象上contextBridge.exposeInMainWorld('platform', arg)
})
于是在vue界面中,我们可以使用以下代码获取平台信息;
index.vue文件
<script setup lang="ts">import { ref, onMounted } from 'vue'const platform = ref<string>('')onMounted(() => {// 此时可以在window对象上直接读取platform数据值platform.value = window.platform})
</script>
二、主进程发送消息,渲染进程进行监听
上面一个示例只有在窗口创建时向渲染进程发送了一个消息,且只发送一次。那假如我现在有个需求是需要监听窗口的变化:最大化、最小化、缩小等等信息。获取窗口最大小的API存在于创建的窗口对象上,那么此时就应该在主进程中监听窗口变化发送消息给渲染进程,并且渲染进程需要监听主进程发送的消息。
主进程 main.js
let appWindow;
const createWindow = () => {appWindow = new BrowserWindow({width: 850,height: 700,webPreferences: {preload: path.join(path.resolve(), 'preload/index.js')}})// appWindow对象上的on方法监听窗口事件appWindow.on('resize', () => {// 当窗口发生变化时,使用webContents.send方法向预加载脚本发送消息,消息名为resizeWindow,并挈带参数为窗口是否最大化appWindow.webContents.send('resizeWindow', appWindow.isMaximized())})
}
那么在预加载脚本中preload/index.js就有了如下代码:
const { contextBridge, ipcRenderer } = require('electron')// 首先向渲染进程中暴露出一个名为resizeWindow的API(名字可自定义),并将此API以对象的形式向外暴露,对象中编写一个监听窗口更新的方法,名为onUpdateWindow
// 此更新方法接收一个回调函数,用于在渲染进程中获取参数
// 此用法成为 高阶函数
// 更新方法的方法体为 ipcRenderer监听主进程发送的resizeWindow事件
// 在接受窗口变化事件的第二个参数中接收变化参数并调用callback()函数,将变化值传递进此回调中
contextBridge.exposeInMainWorld('resizeWindow', {onUpdateWindow: (callback) => ipcRenderer.on('resizeWindow', (_, value) => callback(value)),
})
在渲染进程中:
<script setup lang="ts">
import { ref, onMounted } from 'vue'const isMaxWin = ref<boolean>(false)onMounted(() => {// 调用window对象上的resizeWindow中的onUpdateWindow,并传递一个函数进去,//此函数对应的就是上方的callback,当ipcRenderer监听到事件后调用callback(),// 此回调函数就能够接收到窗口是否最大化的值window.resizeWindow.onUpdateWindow((value: boolean) => {isMaxWin.value = value})
})
</script>
三、渲染进程发送消息到主进程
渲染进程向主进程发送消息也是预加载脚本中向渲染进程暴露出一个API,渲染进程中调用此API,触发预加载脚本中对应的函数,此函数可以通过ipcRenderer调用主进程中的方法。
首先预加载脚本中的代码:
const { contextBridge, ipcRenderer } = require('electron')// 向渲染进程的window对象中绑定languageAPI,此API以对象的形式存在一个setTitle方法
// 此方法接收一个title并在方法体中使用ipcRenderer.invoke调用主进程中名为language:setTitle的监听事件
// 注意:language:setTitle只是自定义的名称,为了更醒目而已,开发者可以自定义其他名称
contextBridge.exposeInMainWorld('language', {setTitle: (title) => ipcRenderer.invoke('language:setTitle', title),
})
主进程中的代码:
const { BrowserWindow, ipcMain} = require('electron');let appWindow;
const createWindow = () => {appWindow = new BrowserWindow({width: 850,height: 700,webPreferences: {preload: path.join(path.resolve(), 'preload/index.js')}})
}
// 预加载脚本中invoke对象的监听事件为ipcMain.handle
// 所以此时主进程会监听名为language:setTitle的事件,并在回调函数中的第二个参数接收参数。
ipcMain.handle('language:setTitle', (_, title) => {// 设置窗口名称appWindow.setTitle(title)
})
在渲染进程中调用预加载脚本中定义的方法:
<script setup lang="ts">
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'const { locale, t } = useI18n()
const changeLanguage = (language: string) => {locale.value = language// 当在界面中触发此方法时 调用window.language.setTitle方法并传入参数window.language.setTitle(t('app.name'))
}
</script>
四、解决预加载脚本暴露在window对象上的数据在ts中报错问题
由于自定义的API名称挂载到了window对象上,window此前并无此API,所以在ts的代码编写中会出现Proerty does not exist on type 'Window & typeof globalThis'
的错误,即使代码可以运行。
所以此时我们需要定义.d.ts文件声明Window的API类型。
在项目根目录或者适合你项目的地方创建任意名称的.d.ts
文件,并编写文件内容:
declare module '*.vue';type handleWindowAPI = {get: () => Promise<boolean>;set: (value: string) => Promise<void>;
}
type languageAPI = {setTitle: (title: string) => void;
}
type darkModeAPI = {toggle: () => Promise<boolean>;
}
type resizeWindowAPI = {onUpdateWindow: (callback: Function) => Promise<boolean>;
}
interface Window {platform: string;language: languageAPI;darkMode: darkModeAPI;handleWindow: handleWindowAPI;resizeWindow: resizeWindowAPI;
}
之后在tsconfig.json
文件中的include属性中加载此ts文件:
{"compilerOptions": {"target": "ES2020","useDefineForClassFields": true,"module": "ESNext","lib": ["ES2020", "DOM", "DOM.Iterable"],"skipLibCheck": true,/* Bundler mode */"moduleResolution": "bundler","allowImportingTsExtensions": true,"resolveJsonModule": true,"isolatedModules": true,"noEmit": true,"jsx": "preserve",/* Linting */"strict": true,"noUnusedLocals": true,"noUnusedParameters": true,"noFallthroughCasesInSwitch": true},// 这里加载项目所有src下以ts结尾的文件"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],"references": [{ "path": "./tsconfig.node.json" }]
}
最后提醒!!!
在预加载脚本中向渲染进程中暴露API时,暴露同一个名称的API的代码只能执行一次,否则将会报错:Cannot bind an API on top of an existing property on the window object
相关文章:
Electron V28主进程与渲染进程互相通信总结
本文示例采用ElectronVue3TS编写,请读者理顺思路,自行带入自己的项目。 注: 读本文前请先搞懂什么是主进程,什么是渲染进程。 在Electron中有着ipcMain和ipcRenderer、contextBridge模块,以及创建窗口对象上的webCont…...
MySQL主从复制详解
目录 1. 主从复制的工作原理 1.1. 主从复制的角色 1.2. 主从复制的流程 2. 配置MySQL主从复制 2.1. 确保主服务器开启二进制日志 2.2. 设置从服务器 2.3. 连接主从服务器 2.4. 启动复制 3. 主从复制的优化与注意事项 3.1. 优化复制性能 3.2. 注意复制延迟 3.3. 处理…...
verilog基础语法-计数器
概述: 计数器是FPGA开发中最常用的电路,列如通讯中记录时钟个数,跑马灯中时间记录,存储器中地址的控制等等。本节给出向上计数器,上下计数器以及双向计数器案例。 内容 1. 向上计数器 2.向下计数器 3.向上向下计数…...
有SCL,SDA,TRIG,I2C的元器件是什么?在哪找?proteus
寻找方法:...
再谈低代码开发——值得所有程序设计和开发者重视的建议!
前几天看到关于“低代码开发”的话题,简单的谈了些自己的看法,也看了一些朋友们各抒己见的好文章,今天想结合我们实际使用的开发平台和大家再做些探讨。 在平台的简介中首先提出了这个大家一定很关心的问题: 一、“为什么使用低代…...
Docker部署MinIO对象存储服务器结合内网穿透实现远程访问
文章目录 前言1. Docker 部署MinIO2. 本地访问MinIO3. Linux安装Cpolar4. 配置MinIO公网地址5. 远程访问MinIO管理界面6. 固定MinIO公网地址 前言 MinIO是一个开源的对象存储服务器,可以在各种环境中运行,例如本地、Docker容器、Kubernetes集群等。它兼…...
USB2.0 Spec
USB System Description A USB system is described by three definitional areas: • USB interconnect • USB devices • USB host USB interconnect The USB interconnect is the manner in which USB devices are connected to and communicate with the host. USB Ho…...
prbs测试
PRBS是 Pseudo Random Binary Sequence 的简称,是一种伪随机序列,用于产生随机数据。 PRBS检测主要应用在设备开局或维护期间,在没有合适误码仪的情况下,使能了PRBS检测功能的设备自行发送PRBS码流,PRBS码流通过被测试网络,经远端设备环回(远端设备需要配置环回),经过PR…...
计算机网络:数据链路层(VLAN)
今天又学到一个知识,加油! 目录 一、传统局域网的局限(促进VLAN的诞生) 二、VLAN简介 三、VLAN的实现 总结 一、传统局域网的局限(促进VLAN的诞生) 缺乏流量隔离:即使把组流量局域化道一个单一交换机中…...
C# WPF上位机开发(动态添加控件)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 写图形界面软件的时候,我们经常会遇到一种情况。那就是图形界面上面,显示的控件可能是不定的。有可能多,也有可…...
MySQL进阶|MySQL中的事务(一)
文章目录 数据库事务MySQL中的存储引擎InnoDB存储引擎架构什么是事务事务的状态总结 数据库事务 MySQL 事务主要用于处理操作量大,复杂度高的数据。比方我想要删除一个用户(销户)以及这个用户的个人信息、订单信息以及其他信息,这…...
设计模式策略模式讲解和代码示例
引言 策略是一种行为设计模式, 它将一组行为转换为对象, 并使其在原始上下文对象内部能够相互替换。 原始对象被称为上下文, 它包含指向策略对象的引用并将执行行为的任务分派给策略对象。 为了改变上下文完成其工作的方式, 其他对象可以使用另一个对象来替换当前链接的策…...
Qt容器QStackedWidget小部件堆栈
# QStackedWidget QStackedWidget是Qt框架中的一个控件,用于在同一区域显示多个子控件,只有一个子控件可见。以下是一些常用的QStackedWidget函数: addWidget(QWidget *widget):向QStackedWidget中添加一个子控件。 insertWidget(int index, QWidget *widget):在指定位置…...
设计模式 简单工厂 工厂方法模式 抽象工厂模式 Spring 工厂 BeanFactory 解析
工厂模式介绍 工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。它是创建型模式。 简单工厂 简单工厂模式是指由一个工厂对象决定创建出哪一种产品类的实例, 但它不属于GOF 23种设计模式 简单工厂适用于工厂类负责创建的对象较少的场景,…...
【Hive_03】单行函数、聚合函数、窗口函数、自定义函数、炸裂函数
1、函数简介2、单行函数2.1 算术运算函数2.2 数值函数2.3 字符串函数(1)substring 截取字符串(2)replace 替换(3)regexp_replace 正则替换(4)regexp 正则匹配(5ÿ…...
RabbitMQ手动应答与持久化
1.SleepUtil线程睡眠工具类 package com.hong.utils;/*** Description: 线程睡眠工具类* Author: hong* Date: 2023-12-16 23:10* Version: 1.0**/ public class SleepUtil {public static void sleep(int second) {try {Thread.sleep(1000*second);} catch (InterruptedExcep…...
java使用枚举类型解决if-else大量堆积
调用代码 import com.example.javaone.kk.MyEnum;public class Gst {public static void main(String[] args) {MyEnum eMyEnum.getById(1);System.out.println(e.getGetSize());} }被调用代码 package com.example.javaone.kk; public enum MyEnum {ENUM1(1,2),ENUM2(2,3),E…...
【数据结构】八大排序之直接插入排序算法
🦄个人主页:修修修也 🎏所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 一.直接插入排序简介及思路 直接插入排序(Straight Insertion Sort)是一种简单直观的插入排序算法. 它的基本操作是: 将一个数据插入到已经排好的有序表中,从而得到一个新的,数…...
网络编程『socket套接字 ‖ 简易UDP网络程序』
🔭个人主页: 北 海 🛜所属专栏: Linux学习之旅、神奇的网络世界 💻操作环境: CentOS 7.6 阿里云远程服务器 文章目录 🌤️前言🌦️正文1.预备知识1.1.IP地址1.2.端口号1.3.端口号与进…...
FreeSWITCH rtp endpoint recvonly
查了下rtp.c的源码,远端端口为0就意味着recvonly,但其实不然,调用switch_rtp_new会马上返回失败 经过反复测试,增加下面几行代码之后终于变成了recvonly: tech_pvt->mode RTP_RECVONLY; rtp_flags[SWITCH_RTP_FLAG_AUTOADJ];…...
Hadoop和Spark的区别
Hadoop 表达能力有限。磁盘IO开销大,延迟度高。任务和任务之间的衔接涉及IO开销。前一个任务完成之前其他任务无法完成,难以胜任复杂、多阶段的计算任务。 Spark Spark模型是对Mapreduce模型的改进,可以说没有HDFS、Mapreduce就没有Spark。…...
英文论文降重修改技巧 papergpt
大家好,今天来聊聊英文论文降重修改技巧,希望能给大家提供一点参考。 以下是针对论文重复率高的情况,提供一些修改建议和技巧,可以借助此类工具: 英文论文降重修改技巧 作为网站编辑,我们经常需要处理大量…...
DevOps搭建(十)-安装Harbor镜像仓库详细步骤
1、下载Harbor 官方地址: https://goharbor.io/ 下载地址: https://github.com/goharbor/harbor/tags 选择文档版本进行下载,这里我们选择v2.7.2版本 2、上传到服务器并解压 上传压缩包到服务器后,解压到/usr/local目录下&a…...
DDA 算法
CAD 算法是计算机辅助设计的算法,几何算法是解决几何问题的算法 CAD 算法是指在计算机辅助设计软件中使用的算法,用于实现各种设计和绘图功能,CAD 广泛应用于建筑、机械、电子等领域,可以大大提高设计效率和精度 绘图算法是 CAD…...
天猫数据平台-淘宝天猫数据-天猫销售数据分析:11月天猫平台滑雪运动装备行业销量翻倍!
随着天气变冷、冬季来临,迎来了疫情后的首个滑雪季,加之自冬奥会结束以来,大众参与冰雪运动的热度持续攀升,因此,冰雪运动的需求正集中释放。 根据相关数据显示,11月以来,全国滑雪场门票预订量较…...
使用OpenCV和PIL库读取图片的区别
OpenCV 和 PIL(Pillow)是两个不同的图像处理库,它们使用不同的数据结构来表示图像。 OpenCV 格式图像: OpenCV 中的图像通常表示为 NumPy 数组。这些数组可以是多维的,例如对于彩色图像,它们是三维数组&am…...
Amazon CodeWhisperer:AI 编程助手
文章作者:prigioni 1. 什么是 Amazon CodeWhisperer? Amazon CodeWhisperer 能够理解以自然语言(英语)编写的注释,并能实时生成多条代码建议,以此提高开发人员生产力。该服务可以直接在集成开发环境&#…...
Linux 使用 Anaconda+Uwsgi 部署 Django项目和前端项目
一、安装Anaconda 使用Anaconda创建python环境的优点: virtualenv只能创建系统原有的python版本,而不能创建创建任意版本的环境 而Anaconda的虚拟环境中,你可以指定任意现存可使用的python环境(包括比原环境版本高的python版本&a…...
分析若依的文件上传处理逻辑
分析若依的文件上传处理逻辑 注:已经从若依框架完成拆分,此处单独分析一下人家精彩的封装,也来理解一下怎么做一个通用的上传接口!如有分析的,理解的不透彻的地方,大家多多包含,欢迎批评指正&am…...
Note3---初阶二叉树~~
目录 前言🍄 1.树概念及结构☎️ 1.1 树的概念🎄 1.2 树的相关概念🦜 1.2.1 部分概念的加深理解🐾 1.2.2 树与非树🪴 1.3 树的表示🎋 1.4 树在实际中的运用(表示文件系统…...
专业做幼儿园网站/线下课程seo
文章目录前言1、search_after原理2、特点使用1、kibana中测试示例2、Java代码示例首次调用:后续调用:转载请标明出处: http://blog.csdn.net/qq_27818541/article/details/109208235 本文出自:【BigManing的博客】 前言 1、search_after原理…...
中国建设银行客服网站/五合一网站建设
C之那些年踩过的坑(三) 作者:刘俊延(Alinshans) 本系列文章针对我在写C代码的过程中,尤其是做自己的项目时,踩过的各种坑。以此作为给自己的警惕。 【版权声明】转载请注明原文来自:…...
wordpress教程 网站标题/站外推广渠道有哪些
“我们把DevOps和研发任务协同结合起来,打破了研发团队的最后一道隔阂。” 往往在产品开发过程中,研发人员需要掌控的最多的工具和平台。 代码,环境,部署,容器,服务器一大堆的工具和平台要使用࿰…...
北京海淀公司注册/长春seo招聘
git push到远程仓库时提示:fatal: The current branch master2 has no upstream branch. To push the current branch and set the remote as upstream, use git push --set-upstream origin master2,如图: 大意是当前分支与远程分支没有建立…...
建站边检站/网络营销推广技巧
目录计数类DP1.整数划分数位DP状压DP树形DP记忆化搜索计数类DP 1.整数划分 题意 : 给定一个数nnn,询问有多少种方法可以将其拆分成多个数的和,包括本身 思路 : 此题模板于 Acwing.自然数的拆分 状态表示与转移同理于01背包记录方案数 状态表示 : f[i]f[i]f[i]表示iii拆分的…...
建设部门网站查询/百度应用商店下载安装
在Android设备中,适配是一个最普遍的问题,Android中因为屏幕分辨率的不同,会导致我们UI的显示会有很大的区别,那么怎么样才能保证同一个界面在不同屏幕中显示效果是一样的呢?这就是我们今天要做的适配,那么…...