欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > Electron(01)

Electron(01)

2025/11/5 3:18:00 来源:https://blog.csdn.net/m0_56799642/article/details/148745805  浏览:    关键词:Electron(01)

Electron

Electron是什么

electron可以使用前端技术开发桌面应用,跨平台性,开发一套应用,可以打包到三个平台。

electron结合Chromium(谷歌内核)和 Node.js 和Native Api

当使用 Electron 时,很重要的一点是要理解 Electron 不是一个 Web 浏览器。 它允许您使用熟悉的 Web 技术构建功能丰富的桌面应用程序

官网:简介 | Electron


Electron广泛应用

使用Electron框架开发的知名软件。

Visual Studio Code、GithubDesktop、Postman、DockerDesktop...


Electron进程模型

主进程(main.js)。运行在node环境

一个应用只会有一个主进程,负责应用的生命周期、展示原生窗口、执行特殊操作和管理渲染进程。

渲染进程(render.js ),运行在浏览器环境

一个应用可以有多个渲染进程,渲染器进程负责展示图形内容。


快速上手

环境安装

node环境(v20.13.1)、npm环境(10.5.2)

测试安装是否成功,按下【win+R】键,输入cmd,打开cmd窗口

输入:node -v // 显示node.js版本

​ npm -v // 显示npm版本

npm config set registry https://registry.npmmirror.com/
 npm i electron -D

main.js

应用的主进程定义在 package.json 中的 main 属性中

"main": "main.js"

main 文件是 Electron 应用的入口。 这个文件控制 主程序 (main process),它运行在 Node.js 环境里,负责控制您应用的生命周期、显示原生界面、执行特殊操作并管理渲染器进程 (renderer processes)

const { app, BrowserWindow, ipcMain, Notification, Menu } = require('electron/main')
const path = require('node:path')
const fs = require('fs')function writeFile(_, data) {fs.writeFileSync('D:/hello.txt', data)
}function readFile() {const res = fs.readFileSync('D:/hello.txt').toString();return res
}
const createWindow = () => {const win = new BrowserWindow({width: 1000,height: 800,icon: path.join(__dirname, 'favicon.ico'),title: '简单网页',webPreferences: {preload: path.join(__dirname, 'preload.js')}})ipcMain.on('file-save', writeFile)ipcMain.handle('file-read', readFile)//自定义菜单项let menuTemp = [{label: '文件',submenu: [{label: '打开文件',click() {console.log('打开一个具体的文件')}},{ label: '打开文件夹' },{label: '关于',role: 'about'}]},{ label: '编辑' }]//生成自定义菜单let menu = Menu.buildFromTemplate(menuTemp)Menu.setApplicationMenu(menu)win.loadFile('index.html')// 创建并显示通知const notification = new Notification({title: '主进程通知',body: '恭喜你,学会了求雨之术,风来~雨来~'}).show();// 确保在窗口创建后调用 openDevTools//win.webContents.on('did-finish-load', () => {//  win.webContents.openDevTools();//});// 定时发送时间给渲染进程(每1秒)setInterval(() => {if (win && !win.isDestroyed()) {win.webContents.send('main-time', new Date().toLocaleTimeString());}}, 1000);
}
app.whenReady().then(createWindow)

app模块:是为了控制整个应用的生命周期设计的。

BrowserWindow 模块:BrowserWindow 类让你有创建一个浏览器窗口的权力

webContents 模块:负责渲染并控制网页,也是 BrowserWindow 对象的属性.


index.html

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';" />
</head><body><div id="time">当前时间:加载中...</div><div class="hint">注意:输入内容,可以保存到d:/hello.txt,点击读取,可以读取该文件内容</div><input id="input" type="text"><button id="btn2">向D盘输入hello.txt</button><br><br><hr><button id="btn3">读取D盘hello.txt</button><script type="text/javascript" src="./render.js"></script>
</body></html>

render.js

const timeElement = document.getElementById('time');
const btn2 = document.getElementById('btn2');
const btn3 = document.getElementById('btn3');
const input = document.getElementById('input');btn2.onclick = () => {myAPI.saveFile(input.value)
}btn3.onclick = async () => {let data = await myAPI.readFile()alert(data)
}// 监听主进程发送的时间消息
myAPI.onMainTime((time) => {timeElement.textContent = `当前时间:${time}`;
});

preload.js

preload.js执行时机:预加载脚本在渲染器加载网页之前注入

预加载脚本preload.js(中间人),它在渲染进程运行(浏览器环境),人家也能访问一部分的node api。

const { contextBridge, ipcRenderer } = require('electron')contextBridge.exposeInMainWorld('myAPI', {saveFile: (data) => {ipcRenderer.send('file-save', data)},readFile: () => {return ipcRenderer.invoke('file-read')},// 监听主进程发送的时间消息onMainTime: (callback) => {ipcRenderer.on('main-time', (event, time) => callback(time))}
})

ipc进程通信

IPC 代表进程间通信。 Electron使用IPC在主进程和渲染器进程之间发送 序列化的JSON消息

remote模块

Electron 官方已经明确表示,remote 模块是一个遗留的 API,不建议在新项目中使用。 他们鼓励开发者迁移到 Context Bridge。

remote 模块安全风险: 正如之前提到的,remote 模块允许渲染进程直接访问主进程的几乎所有对象,这带来了严重的安全风险。 恶意代码可能会利用 remote 模块来执行任意代码,甚至控制整个应用程序。

替代方案: Context Bridge (结合 ipcRenderer 和 ipcMain) 提供了更安全、更可控的进程间通信方式。


[渲染进程]调用[主进程] 无返回

需求:比如在页面上向d盘的文件写内容

主进程 ipcMain.on,写在app.whenReady().then()中

ipcMain.on('file-save', writeFile)function writeFile(_, data) {fs.writeFileSync('D:/hello.txt', data)
}

ipcRender.send 通过预加载脚本暴露了一个单行的 saveFile函数。

const { contextBridge, ipcRenderer } = require('electron')contextBridge.exposeInMainWorld('myAPI', {saveFile: (data) => {ipcRenderer.send('file-save', data)}})

最后在渲染器进程,也就是HTML页面就可以使用暴露出来的saveFile方法了

const btn2 = document.getElementById('btn2');
const input = document.getElementById('input');btn2.onclick = ()=> {myAPI.saveFile(input.value)
}

[渲染进程]调用[主进程] 有返回

双向 IPC 的一个常见应用是从渲染器进程码调用代主进程模块并等待结果,更适合请求-响应模式

需求:在页面上读取d盘的文件内容,点击按钮弹出d盘hello.txt文件内容

主进程 ipcMain.handle,写在app.whenReady().then()中

ipcMain.handle('file-read', readFile)function readFile() {const res = fs.readFileSync('D:/hello.txt').toString();return res
}

ipcRender.invoke 通过预加载脚本暴露了一个单行的 readFile函数。

const { contextBridge, ipcRenderer } = require('electron')contextBridge.exposeInMainWorld('myAPI', {readFile: () => {return ipcRenderer.invoke('file-read')}})

最后在渲染器进程,也就是HTML页面就可以使用暴露出来的readFile方法了

const btn3 = document.getElementById('btn3');
btn3.onclick = async () => {let data = await myAPI.readFile()alert(data)
}

[主进程]调用[渲染进程]

需求:页面显示当前时间,每1秒更新一次,来自主进程定时推送

主进程:webContents.send  发送消息

    // 定时发送时间给渲染进程(每1秒)setInterval(() => {if (win && !win.isDestroyed()) {win.webContents.send('main-time', new Date().toLocaleTimeString());}}, 1000);

ipcRenderer.on 预加载脚本监听主进程消息,暴露出onMainTime函数给渲染进程

callback本质是渲染进程向预加载脚本“注册”的一个“数据接收器”,让预加载脚本能把主进程的数据“交给”渲染进程处理。

const { contextBridge, ipcRenderer } = require('electron')contextBridge.exposeInMainWorld('myAPI', {// 监听主进程发送的时间消息onMainTime: (callback) => {ipcRenderer.on('main-time', (event, time) => callback(time))}
})

渲染进程

渲染进程调用onMainTime时传递了一个callback

const timeElement = document.getElementById('time');//监听主进程发送的时间消息
myAPI.onMainTime((time) => {timeElement.textContent = `当前时间:${time}`;
});

打包应用

electron-builder

配置国内镜像源

// 指定electron 二进制包镜像地址
npm config set ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
npm config set ELECTRON_BUILDER_BINARIES_MIRROR="https://npmmirror.com/mirrors/electron-builder-binaries/"

// 检测npm仓库和electron镜像地址是否设置成功
npm config list

安装打包工具

npm install electron-builder -D

打包应用 electron-builder(做很多自定义的东西)

愉快执行:npm run build,安装包在dist目录,74MB,安装后包含node和chromiun

npm run build

electron-forge

安装打包工具

npm install --save-dev @electron-forge/cli
npx electron-forge import

执行打包

npm run make

执行成功后,默认输出目录为out/make,里面会生成平台对应的分发文件,例如:

  • Windowsout/make/squirrel.windows/x64/my-app-1.0.0 Setup.exe(安装包)、my-app-1.0.0-full.nupkg(更新包)。
  • macOSout/make/dmg/my-app-1.0.0.dmg(磁盘镜像)、out/make/zip/my-app-1.0.0.zip(压缩包)。
  • Linuxout/make/deb/x64/my-app_1.0.0_amd64.deb(Debian包)、out/make/rpm/x64/my-app-1.0.0-1.x86_64.rpm(RPM包)。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词