主进程->渲染进程
sandbox沙盒化配置,默认值false,即不开启沙盒化。nodeIntegration即node环境集成,默认值false,contextIsolation隔离上下文,默认值true。 当主进程不添加任何配置的话,默认处于上下文隔离状态,此时无法在preload(预加载脚本)中访问node API。当设置sandbox:true和nodeIntegration:true,此时沙盒化和覆盖掉node集成配置,同样也无法在preload(预加载脚本)中访问node API。单独设置sandbox:false或者nodeIntegration:true的话,则可以破除限制,在preload(预加载脚本)中可访问node API。
主进程,这里以读取本地json文件内容为例
const { ipcMain } = require('electron')
ipcMain.on('readConfig', (e) => {
fs.readFile('/electron-vite-vue/config.json', 'utf8', (err, data) => {
if (err) {
console.err(err)
} else {
e.sender.send('getConfig', data)
}
})
})
子进程,先向主进程发送正在监听的监听事件,然后再监听主进程发送过来的消息。
const { ipcRenderer } = require('electron')
ipcRenderer.send('readConfig')
ipcRenderer.on('getConfig', (ev, msg) => {
console.log('来自主进程的消息', msg)
})
渲染进程->主进程
情况一,渲染向主发送消息,主接收。
渲染进程:
const { ipcRenderer } = require('electron')
ipcRenderer.send('test1', '我是渲染进程')
主进程:
const { ipcMain } = require('electron')
ipcMain.on('test1',(e,msg)=>{
console.log('receive renderer message',msg)
})
情况二,渲染向主发送消息,主接收后,再回复渲染
渲染进程:
const { ipcRenderer } = require('electron')
ipcRenderer.send('test1', '我是渲染进程')
渲染进程监听主进程回复的
ipcRenderer.on('test2', (_, arg) => {
console.log('receive main message', arg)
})
主进程:
const { ipcMain } = require('electron')
ipcMain.on('test1',(e,msg)=>{
console.log('receive renderer message',msg)
//下面两种发送都可以
e.sender.send('test2','我是主进程');
e.reply('test2','我是主进程')
})
情况三,渲染向主发送消息,主接收后,再回复消息给渲染,渲染等待拿到主回复,返回值状态改变
渲染进程:
注意,渲染进程通过 `ipcRenderer.invoke` 发送消息后,`invoke` 的返回值是一个 `Promise<pending>` 。主进程回复
消息需要通过 `return` 的方式进行回复,而 `ipcRenderer` 只需要等到 `Promise resolve` 即可获取到返回的值。
const { ipcRenderer } = require('electron')
async function invokeMsgToMain(){
const result=await ipcRenderer.invoke('test3','我是渲染进程')
console.log('接收主进程消息',result)
}
invokeMsgToMain()
主进程:
const { ipcMain } = require('electron')
ipcMain.handle('test3', (_, msg) => {
console.log('receive renderer message', msg)
return message
})
情况四,注意,渲染进程通过
ipcRenderer.sendSync发送消息后,主进程回复消息需要通过
e.returnValue 的方式进行回复,如果
event.returnValue 不为
undefined 的话,渲染进程会等待
sendSync 的返回值才执行后面的代码。
渲染进程:
这里页面会卡住,等待3秒后获取到主进程回复后页面渲染恢复正常
const { ipcRenderer } = require('electron')
async function sendSyncMessageToMain() {
const replyMessage = await ipcRenderer.sendSync('test4', '我是来自渲染进程的消息')
console.log('接收主进程消息', replyMessage)
}
sendSyncMessageToMain()
主进程:
ipcMain.on('test4', (ev, msg) => {
console.log('接收渲染进程消息', msg)
setTimeout(() => {
ev.returnValue = '我是来自主进程的回复'
}, 3000)
})
小结:
ipcRenderer.send: 这个方法是异步的,用于从渲染进程向主进程发送消息。它发送消息后不会等待主进程的响应,而是立即返回,适合在不需要等待主进程响应的情况下发送消息。
ipcRenderer.sendSync: 与 ipcRenderer.send
不同,这个方法是同步的,也是用于从渲染进程向主进程发送消息,但是它会等待主进程返回响应。它会阻塞当前进程,直到收到主进程的返回值或者超时。
ipcRenderer.invoke: 这个方法也是用于从渲染进程向主进程发送消息,但是它是一个异步的方法,可以方便地在渲染进程中等待主进程返回 Promise 结果。相对于 send
和 sendSync
,它更适合处理异步操作,例如主进程返回 Promise 的情况。
安全通讯方案:
通过预加载脚本preload.js作为中间桥梁进行通讯,这也是官方推荐的方案。
预加载脚本preload.js
import { contextBridge } from 'electron'
这里补充一点,@electron-toolkit/preload是第三方插件,需下载,内部集成了ipcRenderer、process相关api供其使用
import { electronAPI } from '@electron-toolkit/preload'
if (process.contextIsolated) {
try {
contextBridge.exposeInMainWorld('electron', { electronAPI })
} catch (error) {
console.error(error)
}
} else {
window.electron = electronAPI
}
渲染进程:
electron.electronAPI.ipcRenderer.send('readConfig')
electron.electronAPI.ipcRenderer.on('getConfig', (ev, msg) => {
console.log('来自主进程的消息', msg)
})
主进程:
ipcMain.on('readConfig', (e) => {
fs.readFile('/electron-vite-vue/config.json', 'utf8', (err, data) => {
if (err) {
console.err(err)
} else {
e.sender.send('getConfig', data)
}
})
})