Electron学习笔记(一)

文章目录

      • 相关笔记
      • 笔记说明
    • 一、轻松入门
      • 1、搭建开发环境
      • 2、创建窗口界面
      • 3、调试主进程
    • 二、主进程和渲染进程
      • 1、进程互访
      • 2、渲染进程访问主进程类型
      • 3、渲染进程访问主进程自定义内容
      • 4、渲染进程向主进程发送消息
      • 5、主进程向渲染进程发送消息
      • 6、多个窗口的渲染进程接收主进程发送的消息
      • 7、渲染进程之间消息传递
        • 方法一:利用主进程进行中转
        • 方法二:单向传递

相关笔记

  • Electron学习笔记(一)
  • Electron学习笔记(二)
  • 使用 electron-vite-vue 构建 electron + vue3 项目并打包

笔记说明

文本为学习《Electron 实战 入门、进阶与性能优化 刘晓伦 著》时所记录的笔记 主要将书本上的案例运行一遍,针对原理部分并无相关记录。笔记记录于 2023年9月。

一、轻松入门

1、搭建开发环境

安装 yarn :

npm i -g yarn

创建一个文件夹,进行项目的初始化:

yarn init -y

配置 Electron 的镜像网站:

yarn config set electron_mirror https://registry.npmmirror.com/-/binary/electron/

使用 yarn 安装 Electron:

yarn add electron --dev

2、创建窗口界面

创建一个 index.html 文件,内容如下:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Electron</title>
</head>
<body><h1>Hello World</h1>
</body>
</html>

新建一个 index.js 文件,内容如下:

const {app,BrowserWindow} = require('electron');let win = null;app.on('ready', function() {win = new BrowserWindow({// 为页面集成Node.js环境webPreferences: {nodeIntegration: true}});// 访问资源文件win.loadFile('index.html');// 程序启动后开启 开发者工具// win.webContents.openDevTools();win.on('close',function() {win = null;})
});app.on('window-all-closed',function() {app.quit();
})

更新 package.json 文件:

"scripts": {
"start": "electron ./index.js"
},

启动项目:

yarn start

结果展示:

效果展示

3、调试主进程

点击调试按钮,创建 launch.json 文件 -> 选择Node.js环境

调试

修改 launch.json 文件如下:

{"version": "0.2.0","configurations": [{"name": "调试主进程",// type: 调试环境为 Node.js 环境"type": "node","request": "launch","cwd": "${workspaceRoot}",// runtimeExecutable: 指向的是批处理文件,该批处理文件用于启动 Electron// ${workspaceRoot} 是正在进行调试的程序的工作目录的绝对路径"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron","windows": {"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"},// 此处的参数是主进程程序路径的简写形式,填写 "./index.js" 亦可"args": ["."],"outputCapture": "std"}]
}

快捷键:

Ctrl+Shift+I:打开渲染进程的调试窗口

Ctrl+R:代码修改后,刷新界面

二、主进程和渲染进程

1、进程互访

注:原书籍中的代码由于 Electron 版本的更新,remote 模块无法直接导入使用,需要进行下载:

下载 remote 模块:

yarn add @electron/remote

更新 index.js 文件如下:(主进程代码

const {app,BrowserWindow} = require('electron');app.on('ready', function() {win = new BrowserWindow({// 为页面集成Node.js环境webPreferences: {nodeIntegration: true,contextIsolation: false}});require("@electron/remote/main").initialize();require("@electron/remote/main").enable(win.webContents);// 访问资源文件win.loadFile('index.html');// 程序启动后开启 开发者工具// win.webContents.openDevTools();win.on('close',function() {win = null;})
});app.on('window-all-closed',function() {app.quit();
})

参考链接:https://blog.csdn.net/m0_45961428/article/details/122982510

在 index.html 添加以下代码:

<button id="openDevToolsBtn">打开开发者工具</button>
<script>const remote =require('@electron/remote');document.querySelector('#openDevToolsBtn').addEventListener('click',function() {remote.getCurrentWindow().webContents.openDevTools();})
</script>

运行程序:

yarn start

运行结果:(点击按钮可打开开发者工具)

运行结果

2、渲染进程访问主进程类型

主进程代码:主进程代码

更新 index.html 文件如下:

<button id="makeNewWindow">创建新窗口</button>
<script>const remote = require('@electron/remote');// 在渲染进程中创建一个新的窗口document.querySelector('#makeNewWindow').addEventListener('click',function() {win = new remote.BrowserWindow({webPreferences: {nodeIntegration: true,}});win.loadFile('newWin.html');});
</script>

说明:创建 BrowserWindow 的过程依然在主进程中进行,是由 remote 模块通知主进程完成相应的操作的,主进程创建了 BrowserWindow 对象的实例后,把对象的实例以远程对象的形式返回给渲染进程。

3、渲染进程访问主进程自定义内容

主进程代码:主进程代码

新建文件 mainModel.js:

let {BrowserWindow} = require('electron');exports.makeWin = function() {let win = new BrowserWindow({webPreferences: {nodeIntegration: true,}});return win;
}

更新 index.html 文件如下:

<button id="makeNewWindow2">创建新窗口2</button>
<script>const remote = require('@electron/remote');const mainModel = remote.require('./mainModel');let win2 = null;document.querySelector('#makeNewWindow2').addEventListener('click',function() {win2 = mainModel.makeWin();win2.loadFile('newWin.html');});
</script>

4、渲染进程向主进程发送消息

更新 index.html 文件:

<button id="sendMsg">向主进程发送消息</button>
<script>const {ipcRenderer} = require('electron');document.querySelector('#makeNewWindow2').addEventListener('click',() => {// msg:消息管道的名称ipcRenderer.send('msg',{name: 'xiaom'},{name: 'xiaoh'});});
</script>

index.js 文件添加以下内容:(其余主进程代码见:主进程代码)

const {ipcMain} = require('electron');ipcMain.on('msg',(event,param1,param2) => {console.log(param1);console.log(param2);console.log(event.sender);
})

运行结果:

运行结果

5、主进程向渲染进程发送消息

在主进程 index.js 文件中添加以下代码:

const {app,BrowserWindow} = require('electron');
const {ipcMain} = require('electron');let win = null;app.on('ready', function() {win = new BrowserWindow({// 为页面集成Node.js环境webPreferences: {nodeIntegration: true,contextIsolation: false}});// 监听渲染进程发来的消息,随后再次发回给渲染进程ipcMain.on('msg',(event,param1,param2) => {win.webContents.send('msg_main',param1,param2);})// 访问资源文件win.loadFile('index.html');win.on('close',function() {win = null;})
});

更新渲染进程 index.html 文件如下:

<button id="sendMsg">向主进程发送消息</button>
<script>const {ipcRenderer} = require('electron');// 接收 主进程发送的消息ipcRenderer.on('msg_main',(event,param1,param2) => {console.log(param1);console.log(param2);console.log(event.sender);})document.querySelector('#sendMsg').addEventListener('click',() => {ipcRenderer.send('msg',{name: 'xiaom'},{name: 'xiaoh'});});
</script>

运行程序后 -> 点击按钮(向主进程发送消息) -> Electron 程序控制台将会打印主进程发送来的消息。

运行结果:

运行结果

6、多个窗口的渲染进程接收主进程发送的消息

更新主进程 index.js 文件:

const {app,BrowserWindow} = require('electron');
const {ipcMain} = require('electron');// 接收 渲染进程 发送来的消息 在VSCode控制台打印消息
ipcMain.on('msg',(event,param1,param2) => {console.log(param1);console.log(param2);console.log(event.sender);
});let win = null;app.on('ready', function() {win = new BrowserWindow({// 为页面集成Node.js环境webPreferences: {nodeIntegration: true,contextIsolation: false}});// 为了使 remote 模块能够使用需要执行以下操作require("@electron/remote/main").initialize();require("@electron/remote/main").enable(win.webContents);// 监听 渲染进程 发来的消息,随后再次发回给渲染进程ipcMain.on('msg',(event,param1,param2) => {// 单个窗口时使用:// win.webContents.send('msg_main',param1,param2);// 多个窗口时使用// 方法一:// event.sender.send('msg_main',param1,param2);// 方法二:event.reply('msg_main',param1,param2);})// 访问资源文件win.loadFile('index.html');win.on('close',function() {win = null;})
});app.on('window-all-closed',function() {app.quit();
});

更新 index.html 文件如下:

<button id="makeNewWindow">创建新窗口</button>
<button id="sendMsg">向主进程发送消息</button>
<script>const remote = require('@electron/remote');const { ipcRenderer } = require('electron');// 在渲染进程中创建一个新的窗口document.querySelector('#makeNewWindow').addEventListener('click', function () {win = new remote.BrowserWindow({webPreferences: {nodeIntegration: true,contextIsolation: false}});win.loadFile('newWin.html');});// 监听主进程发送来的消息ipcRenderer.on('msg_main', (event, param1, param2) => {console.log(param1);console.log(param2);console.log(event.sender);})// 点击发送按钮 发送消息至主进程document.querySelector('#sendMsg').addEventListener('click', () => {ipcRenderer.send('msg', { name: 'xiaom' }, { name: 'xiaoh' });});
</script>

newWin.html 文件内容如下:

<h1>newWindow</h1>
<button id="sendMsg2">向主进程发送消息</button>
<script>const { ipcRenderer } = require('electron');// 监听主进程发送来的消息ipcRenderer.on('msg_main', (event, param1, param2) => {console.log(param1);console.log(param2);console.log(event.sender);})// 点击发送按钮 发送消息至主进程document.querySelector('#sendMsg2').addEventListener('click', () => {ipcRenderer.send('msg', { name: 'xiaod' }, { name: 'xiaoc' });});
</script>

7、渲染进程之间消息传递

一个程序有多个窗口,并要在窗口之间传递消息,可以通过主进程中转,此处通过win1先将消息发送给主进程,主进程再将消息发送给win2。

方法一:利用主进程进行中转

窗口(win1) --> 主进程(中转) --> 窗口(win2)

窗口(win2) --> 主进程(中转) --> 窗口(win1)

主进程 index.js 文件内容如下:

const {app,BrowserWindow} = require('electron');
const {ipcMain} = require('electron');let win = null;app.on('ready', function() {win = new BrowserWindow({// 为页面集成Node.js环境webPreferences: {nodeIntegration: true,contextIsolation: false}});require("@electron/remote/main").initialize();require("@electron/remote/main").enable(win.webContents);// 监听 窗口win1 (index.html) 发来的消息ipcMain.on('msg_1',(event,param1,param2) => {// 向 窗口win1 (index.html) 发送消息win.webContents.send('msg_main',param1,param2);});// 访问资源文件win.loadFile('index.html');// 程序启动后开启 开发者工具win.webContents.openDevTools();win.on('close',function() {win = null;})
});app.on('window-all-closed',function() {app.quit();
})

窗口(win1) index.html 文件内容如下:

<h1>win1</h1>
<button id="makeNewWindow">创建新窗口win2</button>
<button id="sendMsg">向主进程发送消息</button>
<script>const remote = require('@electron/remote');const { ipcRenderer } = require('electron');// 在渲染进程中创建一个新的窗口(win2)document.querySelector('#makeNewWindow').addEventListener('click', function () {win2 = new remote.BrowserWindow({webPreferences: {nodeIntegration: true,contextIsolation: false}});win2.loadFile('win2.html');win2.webContents.openDevTools();// 接收 主进程 的消息后 向 win2 发送消息ipcRenderer.on('msg_main', (event, param1, param2) => {win2.webContents.send('msg_win2',param1,param2);});});// 接收 主进程 发送的消息ipcRenderer.on('msg_main', (event, param1, param2) => {console.log(param1);console.log(param2);console.log(event.sender);})// 点击按钮向 主进程 发送消息document.querySelector('#sendMsg').addEventListener('click', () => {ipcRenderer.send('msg_1', { name: 'xiaom' }, { name: 'xiaoh' });});
</script>

窗口(win2) win2.html 文件内容如下:

<h1>win2</h1>
<button id="sendMsg2">向主进程发送消息</button>
<script>const { ipcRenderer } = require('electron');// 接收 窗口 win1 (index.html) 发送来的消息ipcRenderer.on('msg_win2', (event, param1, param2) => {console.log(param1);console.log(param2);console.log(event.sender);})// 点击按钮向 主进程 发送消息document.querySelector('#sendMsg2').addEventListener('click', () => {ipcRenderer.send('msg_1', { name: 'xiaod' }, { name: 'xiaoc' });});
</script>

结果展示:

结果展示

方法二:单向传递

窗口(win1) --> 窗口(win2)

主进程 index.js 文件内容如下:(此方法无需主进程中转,所以主进程无需接收消息)

const {app,BrowserWindow} = require('electron');let win = null;app.on('ready', function() {win = new BrowserWindow({// 为页面集成Node.js环境webPreferences: {nodeIntegration: true,contextIsolation: false}});require("@electron/remote/main").initialize();require("@electron/remote/main").enable(win.webContents);// 访问资源文件win.loadFile('index.html');// 程序启动后开启 开发者工具win.webContents.openDevTools();win.on('close',function() {win = null;})
});app.on('window-all-closed',function() {app.quit();
});

窗口(win1) index.html 文件内容如下:

<h1>win1</h1>
<button id="makeNewWindow">创建新窗口win2</button>
<button id="sendMsg">向窗口win2发送消息</button>
<script>const remote = require('@electron/remote');const { ipcRenderer } = require('electron');// 在渲染进程中创建一个新的窗口(win2)document.querySelector('#makeNewWindow').addEventListener('click', function () {win2 = new remote.BrowserWindow({webPreferences: {nodeIntegration: true,contextIsolation: false}});win2.loadFile('win2.html');win2.webContents.openDevTools();// 获取 窗口(win2) 的 webContents.id 并通过 ipcRenderer.sendTo 方法发送消息至 win2document.querySelector('#sendMsg').addEventListener('click', () => {ipcRenderer.sendTo(win2.webContents.id,'msg_win2', { name: 'xiaom' }, { name: 'xiaoh' });});});</script>

窗口(win2) win2.html 文件内容如下:

<h1>win2</h1>
<script>const { ipcRenderer } = require('electron');// 接收 窗口(win1) 发送来的消息ipcRenderer.on('msg_win2', (event, param1, param2) => {console.log(param1);console.log(param2);console.log(event.sender);});
</script>

结果展示:

结果展示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/323304.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux:进程信号

生活角度的信号 a.信号在生活中&#xff0c;随时可以产生(信号的产生和我是异步的) b.你能认识这个信号 c.我们知道信号产生了&#xff0c;我能识别这个信号&#xff0c;信号该怎么处理 d.我们可能正在做着更重要的事情&#xff0c;把到来的信号暂不处理(1.我记得这个事 2.…

YOLOv9中模块总结补充|RepNCSPELAN4详图

专栏地址&#xff1a;目前售价售价69.9&#xff0c;改进点70 专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;助力高效涨点&#xff01;&#xff01;&#xff01; 1. RepNCSPELAN4详图 RepNCSPELAN4是YOLOv9中的特征提取-融合模块&#xff0c;类似前几…

phpstudy(MySQL启动又立马停止)问题的解决办法

方法一&#xff1a;查看本地安装的MySQL有没有启动 1.鼠标右击开始按钮选择计算机管理 2.点击服务和应用程序 3.找到服务双击 4.找到MySQL服务 5.双击查看是否启动&#xff0c;如启动则停止他&#xff0c;然后确定&#xff0c;重新打开phpstudy,启动Mysql. 方法二&#xff…

Python从0到POC编写--实用小脚本02

爆破脚本&#xff1a; 爆破脚本也是我们经常使用的东西 这里就简单讲讲后台爆破脚本的编写吧 在编写之前&#xff0c;我们先通过访问网站去看看情况 首先我们可以先登录看看 输入账号 admin &#xff0c;密码 12345 后 登录失败&#xff0c;提示 用户名或密码错误 在输入…

苹果新品发布会速览:iPad革新遇市场挑战 | 百能云芯

北京时间5月7日晚&#xff0c;苹果以“放飞吧”为主题&#xff0c;举办了一场不到40分钟的线上新品发布会。在这场发布会上&#xff0c;iPad产品线成为了焦点&#xff0c;M4芯片和OLED技术的融入更是引起了广泛关注。 iPad新篇章&#xff1a;技术革新与市场竞争 时隔18个月&…

WebSocket 多屏同显和异显

介绍 多屏同显:通过在一个应用上进行操作之后,另一个应用也能跟着一起发生改变,例如app1播放了晴天这首音乐,那么app2也要同步播放这首音乐,确保所有屏幕显示的内容完全相同。多屏异显:每个屏幕可以显示不同的内容,或者在内容更新时存在一定的延迟,而不需要严格保持同步…

Linux下的SPI通信

SPI通信 一. 1.SPI简介: SPI 是一种高速,全双工,同步串行总线。 SPI 有主从俩种模式通常由一个主设备和一个或者多个从设备组从。SPI不支持多主机。 SPI通信至少需要四根线,分别是 MISO(主设备数据输入,从设备输出),MOSI (主设数据输出从设备输入),SCLK(时钟信号),CS/SS…

物理层——计算机网络学习笔记二

目录 物理层的基本概念 数据通信的基础知识 物理层下面的传输媒体 信道复用技术 图片大部分来源于谢希仁《计算机网络》教材配套的ppt。 这一样都是介绍一下概念性的东西&#xff0c;了解一下就行&#xff0c;就重要性而言不如后面的内容。 物理层的作用&#xff1a;考虑如何才…

android基础-服务

同样使用intent来传递服务 oncreate是服务第一次启动调用&#xff0c;onStartCommand是服务每次启动的时候调用&#xff0c;也就是说服务只要启动后就不会调用oncreate方法了。可以在myservice中的任何位置调用stopself方法让服务停止下来。 服务生命周期 前台服务类似于通知会…

在Linux操作系统中扩建swap容量

在Linux操作系统上创建硬盘分区不仅可以储存数据&#xff0c;还可以使用创建的硬盘分区去扩展机器上swap分区的大小——去扩展交换工具的容量。 有些软件对于swap分区的大小是有要求的&#xff0c;swap分区的大小小于多少就安装不上软件。 要扩展swap容量要么重装系统&#x…

初学者理解Transformer,本文is all you need

要问现在AI领域哪个概念最热&#xff0c;必然是openAI推出chatGPT之后引发的大模型。然而这项技术的起源&#xff0c;都来自一篇google公司员工的神作“Attention Is All You Need”——本文标题也是一种致敬^_^&#xff0c;目前已有近12万的引用(还在增长)。 在“Attention Is…

【教程】极简Python接入免费语音识别API

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;请不吝给个[点赞、收藏、关注]哦~ 安装库&#xff1a; pip install SpeechRecognition 使用方法&#xff1a; import speech_recognition as srr sr.Recognizer() harvard sr…

C++:哈希表和unordered系列容器的封装

一、unordered系列关联式容器的介绍 在C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可达到log2N&#xff0c;即最差情况下需要比较红黑树的高度次&#xff0c;当树中的节点非常多时&#xff0c;查询效率也不理想。最好的查询是&…

索引失效情况

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;面经 ⛺️稳中求进&#xff0c;晒太阳 一、索引列上运算操作。 不要在索引列上进行运算操作&#xff0c;否则索引会失效。 在tb_user的phone列加上索引&#xff0c;然后进行条件查询&am…

Kafka从0到消费者开发

安装ZK Index of /zookeeper/zookeeper-3.9.2 下载安装包 一定要下载-bin的&#xff0c;不带bin的是源码&#xff0c;没有编译的&#xff0c;无法执行。-bin的才可以执行。 解压 tar -zxvf apache-zookeeper-3.9.2-bin.tar.gz 备份配置 cp zoo_sample.cfg zoo_sample.cfg-b…

调用 gradio 创建聊天网页报错(使用远程服务器)

文章目录 写在前面1、使用默认IP地址&#xff08;失败&#xff09;2、使用本地IP地址&#xff08;失败&#xff09;3、使用远程服务器IP地址&#xff08;成功&#xff09; 写在前面 我复现了github上的 llama-chinese 的工作 使用的是 llama2&#xff0c;环境配置是在远程服务…

指针的奥秘(二):指针与数组的联系+字符指针+二级指针+指针数组+《剑指offer》笔试题

指针 一.指针与数组的联系1.数组名的理解2.使用指针访问数组3.一维数组传参的本质 二.字符指针1.字符指针隐藏秘密2.常量字符串3.《剑指offer》笔试题 三.二级指针四.指针数组1.指针数组模拟二维数组 一.指针与数组的联系 1.数组名的理解 也许大部分人认为数组名就是一个名称&…

使用 PXE+Kickstart 批量网络自动装机

前言&#xff1a; 正常安装系统的话使用u盘一个一个安装会非常慢&#xff0c;所以批量安装的技术就出来了。 一、 概念 PXE &#xff08;Preboot eXecute Environment&#xff0c;预启动执行环境&#xff09;是由 Intel 公司开发的技术&#xff0c;可以让计算机通过网络来启动…

如何判断nat网络?如何内网穿透

大家都清楚&#xff0c;如果你想开车&#xff0c;就必须要给车上一个牌照&#xff0c;随着车辆越来越多&#xff0c;为了缓解拥堵&#xff0c;就需要摇号&#xff0c;随着摇号的人数越来越多&#xff0c;车牌对于想开车的人来说已经成为奢望。在如今的IPv4时代&#xff0c;我们…

生信分析进阶2 - 利用GC含量的Loess回归矫正reads数量

在NGS数据比对后&#xff0c;需要矫正GC偏好引起的reads数量误差可用loess回归算法&#xff0c;使用R语言对封装的loess算法实现。 在NIPT中&#xff0c;GC矫正对检测结果准确性非常重要&#xff0c;具体研究参考以下文章。 Noninvasive Prenatal Diagnosis of Fetal Trisomy…