技術(shù)文檔(參考文檔):https://www.electronjs.org/zh/docs/latest/tutorial/ipc
進程間信號傳遞
1. 渲染器進程到主進程(單向)
(1)主進程,用ipcMain.on()進行監(jiān)聽:
// main.js
const { app, BrowserWindow, ipcMain } = require('electron/main')
...
ipcMain.on('set-title', handleSetTitle)
function handleSetTitle (event, title) {
console.log(title) // 在node.js控制臺打印
}
(2)通過預(yù)加載腳本暴露 ipcRenderer.send。
// preload.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
setTitle: (title) => ipcRenderer.send('set-title', title)
})
(3)渲染器進程:從預(yù)加載腳本中暴露的 window.electronAPI發(fā)送信號。
// 渲染器頁面,render/src/index.html或者render/src/index.vue
const title = ‘標題’
window.electronAPI.setTitle(title)
2.渲染器進程到主進程(雙向)
雙向通信應(yīng)用場景:從渲染器進程代碼調(diào)用主進程模塊并等待結(jié)果
雙向通信的流程:和單向類似,使用的方法名有區(qū)別。
(1)主進程,用ipcMain.handle()進行監(jiān)聽:
// main.js
const { app, BrowserWindow, ipcMain, dialog } = require('electron/main')
...
// 1. 渲染器到主進程(單向):主進程在監(jiān)聽
ipcMain.on('set-title', handleSetTitle)
...
// 2. 渲染器到主進程(雙向):主進程在監(jiān)聽
ipcMain.handle('dialog:openFile', handleFileOpen)
async function handleFileOpen () {
const { canceled, filePaths } = await dialog.showOpenDialog()
if (!canceled) {
return filePaths[0]
}
}
(2)通過預(yù)加載腳本暴露 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)渲染器進程:從預(yù)加載腳本中暴露的 window.electronAPI發(fā)送信號。
// 渲染器頁面,render/src/index.html或者render/src/index.vue
// 2. 渲染器到主進程(雙向)
const filePath = await window.electronAPI.openFile() // 此處必須要await
3. 主進程到渲染器進程
(1)主進程,使用 webContents 模塊發(fā)送消息:
// main.js
const { app, BrowserWindow, ipcMain, dialog } = require('electron/main')
...
// 1. 渲染器到主進程(單向):主進程在監(jiān)聽
ipcMain.on('set-title', handleSetTitle)
...
// 2. 渲染器到主進程(雙向):主進程在監(jiān)聽
ipcMain.handle('dialog:openFile', handleFileOpen)
...
// 3. 主進程到渲染器:主進程發(fā)出信號。
mainWindow.webContents.send('update-counter', 1),
(2)通過預(yù)加載腳本暴露 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)渲染器進程:從預(yù)加載腳本中暴露的 window.electronAPI 監(jiān)聽信號。
// 渲染器頁面,render/src/index.html或者render/src/index.vue
// 1. 渲染器到主進程(單向):渲染器發(fā)出信號
const title = ‘標題’
window.electronAPI.setTitle(title)
// 2. 渲染器到主進程(雙向):渲染器發(fā)出信號,并等待主進程返回結(jié)果
const filePath = await window.electronAPI.openFile() // 此處必須要await
// 3. 主進程到渲染器(單向):渲染器在監(jiān)聽
window.electronAPI.onUpdateCounter((value) => {
console.log(value)
})