前言
最近公司在开发一个基于electron的客户端, 之前没有接触过electron, 刚好趁此机会算是一个总结吧。
electron里面的进程
electron常规拥有两个进程:主进程(main)、渲染进程(render)。
主进程为package.json里面main脚本的进程,而渲染进程是主进程使用 BrowserWindow 实例创建页面。 每个 BrowserWindow 实例都在自己的渲染进程里运行页面。 当一个 BrowserWindow 实例被销毁后,相应的渲染进程也会被终止。
主进程与渲染进程的区别
- 主进程是管理所有的web渲染进程,且唯一。渲染进程只关注自己渲染的web页面,且独立。
- 渲染进程不允许调用GUI相关的原生api, 如果要调用必须与主进程通信, 利用主进程的能力调用。
主进程与渲染进程如何通信
electron提供了很多主进程与渲染进程通信的方法:如主进程使用ipcMain,渲染进程使用ipcRenderer方法相互通信。也可以渲染进程使用remote模块直接调用主进程方法进行通信。本次将介绍这两种进程间通信的方法。
- 使用remote方法通信
1 2 3 4 5 6
| let msg = ''
function changeMsg(m) { msg = m }
|
1 2 3 4
| const changeMsg = require('electron').remote.getGlobal(changeMsg)
changeMsg('hello I`m render')
|
上例近演示调用main进程全局方法进行通信, 类似回调句柄转换通信。remote模块提供我们四个方法require()(获得相对main脚本路径的引入)、getCurrentWindow()(获得渲染进程当前窗口)、getCurrentWebContents()(获得渲染进程当前内容)、getGlobal(name)(获得主进程对应name的属性、方法)remote方法本身会返回主进程的electron对象本身,因此具有此对象所有方法和能力。
- 使用ipcMain和ipcRenderer
首先这两个模块本身是一个EventEmitter类的实例,这意味着其拥有EventEmitter的所有方法,包括addEventListener和removeEventListener等方法。这里仅演示发送同步和异步事件,以及主进程主动向渲染进程推送事件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| const { app, BrowserWindow, ipcMain } = require('electron')
ipcMain.on('asynchronous-message', (evt, msg) => { console.log(msg) evt.sender.send('asynchronous-reply', 'pong') })
ipcMain.on('synchronous-message', (evt, msg) => { console.log(msg) evt.returnValue = 'pong' })
app.on('ready', () => { win = new BrowserWindow({width: 800, height: 600}) win.loadURL(`file://${__dirname}/index.html`) win.webContents.on('did-finish-load', () => { win.webContents.send('main-push-msg', 'whoooooooh!') }) })
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const {ipcRenderer} = require('electron')
let sendSyncReturnMsg = ipcRenderer.sendSync('synchronous-message', 'ping') console.log(sendSyncReturnMsg)
ipcRenderer.on('asynchronous-reply', (evt, msg) => { console.log(msg) })
ipcRenderer.send('asynchronous-message', 'ping')
ipcRenderer.on('main-push-msg', (evt, msg) { console.log(msg) })
|
至此electron中main线程与render线程通信常用方法已介绍完毕。