Electron中的IPC通訊總結
單向通訊( 渲染進程 -> 主進程 )
// 主進程 main.js
ipcMain.on('set-title', (event, title) => {
})
// 預加載腳本 preload.js
const { contextBridge, ipcRenderer } = require('electron/renderer')
contextBridge.exposeInMainWorld('electronAPI', {
setTitle: (title) => ipcRenderer.send('set-title', title)
})
// 實際調用,渲染進程
setButton.addEventListener('click', () => {
const title = titleInput.value
window.electronAPI.setTitle(title)
})
單向通訊( 主進程 -> 渲染進程 )
將消息從主進程發送到渲染器進程時,需要指定是哪一個渲染器接收消息。消息需要通過WebContents實例發送到渲染器進程。此WebContents實例包含一個send方法,其使用方式與ipcRenderer.send相同。
對于從主進程到渲染器進程的 IPC,沒有與
ipcRenderer.invoke等效的 API。 不過,您可以從ipcRenderer.on回調中將回復發送回主進程(通過 單向通訊 渲染進程 -> 主進程)。
// 主進程 main.js
function createWindow () {
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
mainWindow.webContents.send('update-counter', 1)
mainWindow.loadFile('index.html')
}
// 預加載腳本 preload.js
const { contextBridge, ipcRenderer } = require('electron/renderer')
contextBridge.exposeInMainWorld('electronAPI', {
onUpdateCounter: (callback) => ipcRenderer.on('update-counter', (_event, value) => callback(value)),
})
// 實際調用,渲染進程
const counter = document.getElementById('counter')
window.electronAPI.onUpdateCounter((value) => {
const oldValue = Number(counter.innerText)
const newValue = oldValue + value
counter.innerText = newValue.toString()
})
雙向通訊(渲染進程 <-> 主進程)
// 方法1:渲染進程請求,主進程方法,并等待其結果;(ipcRenderer.invoke 和 ipcMain.handle 配對使用)
// 示例:從渲染器進程打開一個原生的文件對話框,并返回所選文件的路徑。
// 主進程 main.js
async function handleFileOpen () {
const { canceled, filePaths } = await dialog.showOpenDialog()
if (!canceled) {
return filePaths[0]
}
}
ipcMain.handle('dialog:openFile', handleFileOpen)
// 預加載腳本 preload.js
const { contextBridge, ipcRenderer } = require('electron/renderer')
contextBridge.exposeInMainWorld('electronAPI', {
openFile: () => ipcRenderer.invoke('dialog:openFile')
})
// 實際調用,渲染進程
const btn = document.getElementById('btn')
const filePathElement = document.getElementById('filePath')
btn.addEventListener('click', async () => {
const filePath = await window.electronAPI.openFile()
filePathElement.innerText = filePath
})
// 方法2: 單向通信的 ipcRenderer.send API 也可用于雙向通信。 這是在 Electron 7 之前通過 IPC 進行異步雙向通信的推薦方式。
// 主進程 main.js
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg) // 在 Node 控制臺中打印“ping”
// 作用如同 `send`,但返回一個消息,到發送原始消息的渲染器
event.reply('asynchronous-reply', 'pong')
})
// 預加載腳本 preload.js
const { ipcRenderer } = require('electron')
ipcRenderer.on('asynchronous-reply', (_event, arg) => {
console.log(arg) // 在 DevTools 控制臺中打印“pong”
})
ipcRenderer.send('asynchronous-message', 'ping')
// 方法3: ipcRenderer.sendSync API 向主進程發送消息,并 同步 等待響應。
// 主進程 main.js
const { ipcMain } = require('electron')
ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg) // 在 Node 控制臺中打印“ping”
event.returnValue = 'pong'
})
// 預加載腳本 preload.js
const { ipcRenderer } = require('electron')
const result = ipcRenderer.sendSync('synchronous-message', 'ping')
console.log(result) // 在 DevTools 控制臺中打印“pong”
雙向通訊(渲染進程 <-> 渲染進程)
沒有直接的方法可以使用
ipcMain和ipcRenderer模塊在 Electron 中的渲染器進程之間發送消息。 為此,您有兩種選擇:
- 將主進程作為渲染器之間的消息代理。 這需要將消息從一個渲染器發送到主進程,然后主進程將消息轉發到另一個渲染器。
- 將MessagePort從主進程傳遞到兩個渲染進程。 這將允許在初始設置后渲染器之間直接進行通信。
// 在兩個渲染進程之間建立 MessageChannel
// 在這個示例中,主進程設置了一個MessageChannel,然后將每個端口發送給不同的渲染進程。 這樣可以讓渲染進程彼此之間發送消息,而無需使用主進程作為中轉。
// 主進程 main.js
const { BrowserWindow, app, MessageChannelMain } = require('electron')
app.whenReady().then(async () => {
// 創建窗口
const mainWindow = new BrowserWindow({
show: false,
webPreferences: {
contextIsolation: false,
preload: 'preloadMain.js'
}
})
const secondaryWindow = new BrowserWindow({
show: false,
webPreferences: {
contextIsolation: false,
preload: 'preloadSecondary.js'
}
})
// 建立通道
const { port1, port2 } = new MessageChannelMain()
// webContents準備就緒后,使用postMessage向每個webContents發送一個端口。
mainWindow.once('ready-to-show', () => {
mainWindow.webContents.postMessage('port', null, [port1])
})
secondaryWindow.once('ready-to-show', () => {
secondaryWindow.webContents.postMessage('port', null, [port2])
})
})
// 預加載腳本 preload.js
const { ipcRenderer } = require('electron')
ipcRenderer.on('port', e => {
// 接收到端口,使其全局可用。
window.electronMessagePort = e.ports[0]
window.electronMessagePort.onmessage = messageEvent => {
// 處理消息
}
})

浙公網安備 33010602011771號