4

Electron主进程与渲染进程的通信

 2 years ago
source link: https://direct5dom.github.io/2022/08/23/Electron%E4%B8%BB%E8%BF%9B%E7%A8%8B%E4%B8%8E%E6%B8%B2%E6%9F%93%E8%BF%9B%E7%A8%8B%E7%9A%84%E9%80%9A%E4%BF%A1/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

最近写了一个Vue+Electron实现的Markdown编辑器:Direct5dom/vue-markdown

得益于Vue的低门槛,Web部分的开发很容易就完成了,但是到Electron部分时遭遇了难题。

我想使用Electron原生的导航栏来实现打开文件、保存文件等功能,而导航栏的相关配置位于主进程,在主进程无法调用渲染进程的方法、函数,因此需要完成主进程与渲染进程的通信。

用到的相关模块

  • ipcMain - 事件发射器。在主进程中使用时,它可以处理从渲染进程发送的异步和同步消息。从渲染进程发出的消息将被发射到这个模块。
  • ipcRenderer - 事件发射器。它提供了一些方法,它可以从渲染进程向主进程发送同步和异步的消息。也可以接收来自主进程的回复。
  • webContents - 事件发射器。它负责渲染和控制一个网页,是BrowserWindow对象的一个属性。它提供了一个.send可以从主进程发送消息到渲染进程。

渲染进程主动向主进程发送消息

最简单的异步通信

我们在HTML中设置好按钮:

<button id="btn">发送通知</button>

在渲染进程 (renderer.js) 中设置发送器.send

const { ipcRenderer } = require("electron");
const oBtn = document.getElementById("btn");

oBtn.onclick = function() {
ipcRenderer.send("sendMessage","this is render");
}

在主进程 (main.js) 中设置监听器.on

const { ipcMain } = require("electron");

ipcMain.on("sendMessage",(event,data) => {
console.log(data);
})

执行结果:

# 主进程控制台
this is render

主进程在收到消息后回复渲染进程

在渲染进程 (renderer.js) 中设置发送器.send和监听器.on

const { ipcRenderer } = require("electron");
const oBtn = document.getElementById("btn");


oBtn.onclick = function() {
ipcRenderer.send("sendMessage","this is renderer");
}

ipcRenderer.on("sendMain",(event,data) => {
console.log(data);
})

在主进程 (main.js) 中设置监听器.on,并设置.sendevent

const { ipcMain } = require("electron");

ipcMain.on("sendMessage",(event,data) => {
console.log(data);
event.sender.send("sendMain","this is a main")
})

执行结果:

# 主进程控制台
this is render
# 渲染进程控制台
this is a main

在渲染进程 (renderer.js) 中设置同步发送器.sendSync

const { ipcRenderer } = require("electron");
const oBtn = document.getElementById("btn");

oBtn.onclick = function() {
let res = ipcRenderer.sendSync("sendMessage","this is renderer");
console.log(res)
}

在主进程 (main.js) 中设置监听器.on,并设置.returnValueevent

const { ipcMain } = require("electron");

ipcMain.on("sendMessage",(event,data) => {
console.log(data);
event.returnValue = "this is main"
})

执行结果:

# 主进程控制台
this is render
# 渲染进程控制台
this is a main

主进程主动向渲染进程发送消息

上面的方法都是从渲染进程主动发送消息到主进程的方法。你可能会下意识的类比ipcRenderer.send使用ipcMain.send,然而ipcMain并没有提供这个方法,详见:ipcMain | Electron (electronjs.org)

而要完成这个需求,我们需要用到另一个事件发射器——webContents。他是BrowserWindow的一个属性。

一个简单的案例:

主进程 (main.js) 创建BrowserWindow,并设置webContents.send

const mainWindow = new BrowserWindow({
// ...
});

mainWindow.webContents.send("sendMain","this is main");

在渲染进程 (renderer.js) 中设置监听器.on

ipcRenderer.on("openFilePath", (event, data) => {
console.log(data);
});

执行结果:

# 渲染进程控制台
this is a main

electron中渲染进程与主进程间的通信 - 知乎 (zhihu.com)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK