技术文档(参考文档):https://www.electronjs.org/zh/docs/latest/tutorial/ipc
进程间信号传递
1. 渲染器进程到主进程(单向)
(1)主进程,用ipcMain.on()进行监听:
// main.js
const { app, BrowserWindow, ipcMain } = require('electron/main')
...
ipcMain.on('set-title', handleSetTitle)
function handleSetTitle (event, title) {
console.log(title) // 在node.js控制台打印
}
(2)通过预加载脚本暴露 ipcRenderer.send。
// preload.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
setTitle: (title) => ipcRenderer.send('set-title', title)
})
(3)渲染器进程:从预加载脚本中暴露的 window.electronAPI发送信号。
// 渲染器页面,render/src/index.html或者render/src/index.vue
const title = ‘标题’
window.electronAPI.setTitle(title)
2.渲染器进程到主进程(双向)
双向通信应用场景:从渲染器进程代码调用主进程模块并等待结果
双向通信的流程:和单向类似,使用的方法名有区别。
(1)主进程,用ipcMain.handle()进行监听:
// main.js
const { app, BrowserWindow, ipcMain, dialog } = require('electron/main')
...
// 1. 渲染器到主进程(单向):主进程在监听
ipcMain.on('set-title', handleSetTitle)
...
// 2. 渲染器到主进程(双向):主进程在监听
ipcMain.handle('dialog:openFile', handleFileOpen)
async function handleFileOpen () {
const { canceled, filePaths } = await dialog.showOpenDialog()
if (!canceled) {
return filePaths[0]
}
}
(2)通过预加载脚本暴露 ipcRenderer.invoke。
// preload.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
// 1. 渲染器到主进程(单向)
setTitle: (title) => ipcRenderer.send('set-title', title)
// 2. 渲染器到主进程(双向)
openFile: () => ipcRenderer.invoke('dialog:openFile')
})
(3)渲染器进程:从预加载脚本中暴露的 window.electronAPI发送信号。
// 渲染器页面,render/src/index.html或者render/src/index.vue
// 2. 渲染器到主进程(双向)
const filePath = await window.electronAPI.openFile() // 此处必须要await
3. 主进程到渲染器进程
(1)主进程,使用 webContents 模块发送消息:
// main.js
const { app, BrowserWindow, ipcMain, dialog } = require('electron/main')
...
// 1. 渲染器到主进程(单向):主进程在监听
ipcMain.on('set-title', handleSetTitle)
...
// 2. 渲染器到主进程(双向):主进程在监听
ipcMain.handle('dialog:openFile', handleFileOpen)
...
// 3. 主进程到渲染器:主进程发出信号。
mainWindow.webContents.send('update-counter', 1),
(2)通过预加载脚本暴露 ipcRenderer.on
// preload.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
// 1. 渲染器到主进程(单向)
setTitle: (title) => ipcRenderer.send('set-title', title)
// 2. 渲染器到主进程(双向)
openFile: () => ipcRenderer.invoke('dialog:openFile')
// 3. 主进程到渲染器
onUpdateCounter: (callback) => ipcRenderer.on('update-counter', (_event, value) => callback(value))
})
(3)渲染器进程:从预加载脚本中暴露的 window.electronAPI 监听信号。
// 渲染器页面,render/src/index.html或者render/src/index.vue
// 1. 渲染器到主进程(单向):渲染器发出信号
const title = ‘标题’
window.electronAPI.setTitle(title)
// 2. 渲染器到主进程(双向):渲染器发出信号,并等待主进程返回结果
const filePath = await window.electronAPI.openFile() // 此处必须要await
// 3. 主进程到渲染器(单向):渲染器在监听
window.electronAPI.onUpdateCounter((value) => {
console.log(value)
})