最近在使用 Electron,今天这篇文章写一下 Electron 的主进程和渲染进程的通信。
Electron
首先来介绍一下 Electron,我们知道以前开发桌面应用都是 C# 等技术,而 Electron 基于 Chromium 和 Node.js, 让你可以使用 HTML, CSS 和 JavaScript 构建的桌面应用。Electron 兼容 Mac、Windows 和 Linux,可以构建出三个平台的应用程序。这让我们前端开发人员又可以涉及到更多领域。
进程
Electron 的进程和我们计算机的进程一样,我们知道每个进程都拥有自己的独立资源,每个进程之间都是隔离的。而 Electron 有两种进程:主进程 和 渲染进程。
我们使用 官方的 electron-quick-start 快速生成一个 Electron 的项目结构,可以看到 package.json 的 main 脚本的进程被称为主进程。在这里是 main.js ,当然可以自定义文件名,只有更改对应的 package.json 里 main 字段就行。 一个 Electron 应用总是有且只有一个主进程。
主进程使用 BrowserWindow 实例创建页面。 每个 BrowserWindow 实例都在自己的渲染进程里运行页面。 当一个 BrowserWindow 实例被销毁后,相应的渲染进程也会被终止。一个 Electron 应用可以有多个渲染进程。
主进程和渲染进程的区别
这里引用官网的介绍:
主进程管理所有的web页面和它们对应的渲染进程。 每个渲染进程都是独立的,它只关心它所运行的 web 页面。 在页面中调用与 GUI 相关的原生 API 是不被允许的,因为在 web 页面里操作原生的 GUI 资源是非常危险的,而且容易造成资源泄露。 如果你想在 web 页面里使用 GUI 操作,其对应的渲染进程必须与主进程进行通讯,请求主进程进行相关的 GUI 操作。
主进程主要用来操作 系统 API 和 Node.js 的API,而渲染进程则只关注渲染层面的事情。
那么问题来了,我在渲染进程点击一个按钮,新打开一个窗口,这时候就需要给主进程发消息,由主进程来操作 API。
ipcMain/ipcRenderer
渲染进程使用 ipcRenderer 模块进行通信。
import { ipcRenderer } from 'electron'
// 向主进程发送,新建窗口
newModal (item) {
ipcRenderer.send('newModal',item)
}
主进程使用 ipcMain 模块进行通信;
// 接受来自渲染进程的消息
ipcMain.on('newModal',(e,arg)=>
{
// 新建子窗口
createModalWindow(arg)
})
有没有发现这种方式和 Node.js 的 EventEmitter 或者Vue的 emit&on 很像。是的,其实他们就是 Node.js 的 EventEmitter 的实例。
remote
接下来介绍另一种通信方式:remote
const { BrowserWindow } = require('electron').remote
let newWindow = null;
newModal (item) {
newWindow = new BrowserWindow({
height: 640,
useContentSize: true,
width: 550,
frame: false,
parent: mainWindow,
icon: path.resolve(__static, 'icon.ico')
})
}
区别
使用ipcMain/ipcRenderer通信,业务逻辑同时存在于主进程和渲染进程的代码中。优点是逻辑解耦,渲染进程还是只负责渲染,由主进程去进行系统 API 操作。缺点是很多产生 event handler。
使用 remote 通信,渲染进程通过remote来获取主进程的模块,实现业务逻辑。优点是业务逻辑只存在于渲染进程,减少主进程冗余的 event handler 代码。
两种方式都可以实现进程间通信,具体还是要看需求和代码组织结构来决定使用哪种方式。
结语
这篇文章也是当做自己的学习笔记,内容比较浅薄,欢迎大家多多讨论。