Electron 主进程与渲染进程通信

4,735 阅读3分钟

最近在使用 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 代码。

两种方式都可以实现进程间通信,具体还是要看需求和代码组织结构来决定使用哪种方式。

结语

这篇文章也是当做自己的学习笔记,内容比较浅薄,欢迎大家多多讨论。