electron进程间通信


Electron 应用程序的结构非常相似。 作为应用开发者,你将控制两种类型的进程:主进程渲染器进程。 这类似于上文所述的 Chrome 的浏览器和渲染器进程。

主进程


每个 Electron 应用都有一个单一的主进程,作为应用程序的入口点。 主进程在 Node.js 环境中运行,这意味着它具有 require 模块和使用所有 Node.js API 的能力。

渲染器进程


每个 Electron 应用都会为每个打开的 BrowserWindow ( 与每个网页嵌入 ) 生成一个单独的渲染器进程。 洽如其名,渲染器负责 渲染 网页内容。 所以实际上,运行于渲染器进程中的代码是须遵照网页标准的 (至少就目前使用的 Chromium 而言是如此) 。

Preload 脚本


预加载(preload)脚本包含了那些执行于渲染器进程中,且先于网页内容开始加载的代码 。 这些脚本虽运行于渲染器的环境中,却因能访问 Node.js API 而拥有了更多的权限。

上下文隔离


上下文隔离功能将确保您的 预加载脚本 和 Electron的内部逻辑 运行在所加载的 webcontent网页 之外的另一个独立的上下文环境里。 这对安全性很重要,因为它有助于阻止网站访问 Electron 的内部组件 和 您的预加载脚本可访问的高等级权限的API 。

preload.js

// 在上下文隔离启用的情况下使用预加载
const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
  doAThing: () => {}
})

renderer.js

// 在渲染器进程使用导出的 API
window.myAPI.doAThing()

模式 1:渲染器进程到主进程(单向)ipcMain.on和ipcRenderer.send

主进程:ipcMain.on(eventname,callback)
接收渲染进程发过来的事件和参数,注意回调第一个参数是event,后面是参数

main

const { app, BrowserWindow, ipcMain } = require('electron')
//..............
ipcMain.on('set-title', (event, title) => {
    const webContents = event.sender
    const win = BrowserWindow.fromWebContents(webContents)
    win.setTitle(title)
  })
//.................

渲染进程:ipcRenderer.send(eventname, arguments)
把ipcRender事件暴露给网页使用,附着到window上,因为默认上下文隔离,所以要使用contextBridge.exposeInMainWorld

preload

const { contextBridge, ipcRenderer } = require('electron')
//..................
contextBridge.exposeInMainWorld('electronAPI', {
  setTitle: (title) => ipcRenderer.send('set-title', title)
})
//省略

页面js中通过window对象获取暴露出的electronAPI调用事件,传递消息
window.electronAPI.???

render

const setButton = document.getElementById('btn')
const titleInput = document.getElementById('title')
setButton.addEventListener('click', () => {
  const title = titleInput.value
  window.electronAPI.setTitle(title)
})

模式 2:渲染器进程到主进程(双向)ipcMain.handle和ipcRenderer.invoke

主进程:ipcMain.handle(eventname,callback)
main.js

const { app, BrowserWindow, ipcMain, dialog } = require('electron')
const path = require('path')

async function handleFileOpen () {
  const { canceled, filePaths } = await dialog.showOpenDialog()
  if (!canceled) {
    return filePaths[0]
  }
}
ipcMain.handle('dialog:openFile', handleFileOpen)

染进程:ipcRenderer.invoke(eventname)
preload.js

const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
  openFile: () => ipcRenderer.invoke('dialog:openFile')
})

renderer.js

const btn = document.getElementById('btn')
const filePathElement = document.getElementById('filePath')

btn.addEventListener('click', async () => {
  const filePath = await window.electronAPI.openFile()
  filePathElement.innerText = filePath
})

注意 由于ipcRenderer.invoke()返回的是一个promise对象,想要获取到返回的值,需要使用.then()或者await获取返回值.

模式 3:主进程到渲染器进程 (单双向)mainWindow.webContents.send和ipcRenderer.on

将消息从主进程发送到渲染器进程时,需要指定是哪一个渲染器接收消息。 消息需要通过其 WebContents 实例发送到渲染器进程。 此 WebContents 实例包含一个 send 方法,其使用方式与 ipcRenderer.send 相同。
主进程:
main.js

1. 使用 webContents 模块发送消息
对于此演示,我们需要首先使用 Electron 的 Menu 模块在主进程中构建一个自定义菜单,该模块使用 webContents.send API 将 IPC 消息从主进程发送到目标渲染器。

  const mainWindow = new BrowserWindow({
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })


mainWindow.webContents.send('update-counter', -1)

渲染进程:
preload.js

const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
  onUpdateCounter: (callback) => ipcRenderer.on('update-counter', callback)
})

rederer.js

const counter = document.getElementById('counter')

window.electronAPI.onUpdateCounter((_event, value) => {
  const oldValue = Number(counter.innerText)
  const newValue = oldValue + value
  counter.innerText = newValue
})

可选:返回一个回复
对于从主进程到渲染器进程的 IPC,没有与 ipcRenderer.invoke 等效的 API。 不过,您可以从 ipcRenderer.on 回调中将回复发送回主进程。
我们可以对前面例子的代码进行略微修改来演示这一点。 在渲染器进程中,使用 event 参数,通过 counter-value 通道将回复发送回主进程。

renderer.js (Renderer Process)

const counter = document.getElementById('counter')

window.electronAPI.onUpdateCounter((event, value) => {
  const oldValue = Number(counter.innerText)
  const newValue = oldValue + value
  counter.innerText = newValue
  event.sender.send('counter-value', newValue)
})

在主进程中,监听 counter-value 事件并适当地处理它们。
main.js (Main Process)

// ...
ipcMain.on('counter-value', (_event, value) => {
  console.log(value) // will print value to Node console
})
// ...

相关推荐

  1. Electron 进程通信

    2024-05-13 08:48:07       29 阅读
  2. Electron vue 进程消息通行

    2024-05-13 08:48:07       34 阅读
  3. Python进程通信

    2024-05-13 08:48:07       67 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-13 08:48:07       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-13 08:48:07       100 阅读
  3. 在Django里面运行非项目文件

    2024-05-13 08:48:07       82 阅读
  4. Python语言-面向对象

    2024-05-13 08:48:07       91 阅读

热门阅读

  1. 记一次requests.get()返回数据乱码问题

    2024-05-13 08:48:07       32 阅读
  2. Sass详解

    2024-05-13 08:48:07       35 阅读
  3. 如何加密Oracle后台存储过程

    2024-05-13 08:48:07       30 阅读
  4. Windows环境docker安装MySQL挂载配置不生效问题处理

    2024-05-13 08:48:07       30 阅读
  5. react组件渲染优化-类组件渲染优化

    2024-05-13 08:48:07       44 阅读
  6. vue3 <script setup> 形式父子组件传值

    2024-05-13 08:48:07       26 阅读
  7. 文心一言指令

    2024-05-13 08:48:07       36 阅读
  8. [初学rust] 01_简单打印

    2024-05-13 08:48:07       28 阅读
  9. C语言-STM32-定时器:定时器的输入捕获

    2024-05-13 08:48:07       33 阅读
  10. Rust 标准库的结构及其模块路径

    2024-05-13 08:48:07       31 阅读