Skip to content

二、进程通信

一、渲染器进程到主进程(单向)

  1. 预加载脚本

    注册apiKey

    • apiKey string - 将 API 注入到 窗口 的键。 API 将可通过 window[apiKey] 访问。
    • api any - 你的 API可以是什么样的以及它是如何工作的相关信息如下。
    js
    contextBridge.exposeInMainWorld('electronAPI', {
      setTitle: (title) => ipcRenderer.send('set-title', title)
    })
  2. 渲染进程

通过window属性,调用预加载脚本的方法

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
  </head>
  <body>
    Title: <input id="title"/>
    <button id="btn" type="button">Set</button>
    <script src="./renderer.js"></script>
  </body>
</html>

renderer

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

此时,渲染进程使用预加载脚本向主进程发送了字符串

  1. 主进程

    应用程序加载好后,在whenReady中加载预加载脚本传递过来的参数

    js
    function handleSetTitle (event, title) {
      const webContents = event.sender
      const win = BrowserWindow.fromWebContents(webContents)
      win.setTitle(title)
    }
    
    
    app.whenReady().then(() => {
      ipcMain.on('set-title', handleSetTitle)
      createWindow()
    })

二、渲染器进程到主进程(双向)

说明

双向 IPC 的一个常见应用是从渲染器进程代码调用主进程模块并等待结果。 这可以通过将 ipcRenderer.invokeipcMain.handle 搭配使用来完成。

js
async function handleFileOpen () {
  const { canceled, filePaths } = await dialog.showOpenDialog({})
  if (!canceled) {
    return filePaths[0]
  }
}

app.whenReady().then(() => {
  ipcMain.handle('dialog:openFile', handleFileOpen)
  createWindow()
})
js
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
  openFile: () => ipcRenderer.invoke('dialog:openFile')
})
js
btn.addEventListener('click', async () => {
  const filePath = await window.electronAPI.openFile()
  filePathElement.innerText = filePath
})

三、主进程到渲染进程

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Menu Counter</title>
  </head>
  <body>
    Current value: <strong id="counter">湖北师范大学</strong>
    <script src="./renderer.js"></script>
  </body>
</html>
js
function createWindow() {
  const mainWindow = new BrowserWindow({
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  mainWindow.loadFile('index.html').then(() => {
    mainWindow.webContents.send("counter-value", "黄达全")
  })
}
js
const { contextBridge, ipcRenderer } = require('electron/renderer')

contextBridge.exposeInMainWorld('electronAPI', {
  onUpdateCounter: (callback) => ipcRenderer.on('counter-value', (_event, value) => callback(value))
})
js
const counter = document.getElementById('counter')

window.electronAPI.onUpdateCounter((value) => {
  const oldValue = counter.innerText

  console.log(oldValue);

  setTimeout(() => {
    counter.innerText = value
    console.log(value);
  }, 3000);
})

四、渲染器进程到渲染器进程

说明

没有直接的方法可以使用 ipcMainipcRenderer 模块在 Electron 中的渲染器进程之间发送消息

不过有俩种替代方案

  • 将主进程作为渲染器之间的消息代理。 这需要将消息从一个渲染器发送到主进程,然后主进程将消息转发到另一个渲染器。
  • 从主进程将一个 MessagePort传递到两个渲染器。 这将允许在初始设置后渲染器之间直接进行通信。