进程间通信 IPC(Inter-Process Communication)
Electron 应用由多个进程组成, 包括一个主进程和一个或多个渲染进程
进程之间由于安全原因不能直接共享数据, 需通过 IPC 来进行数据交换
新版 Electron 推荐使用双向通信 ipcRenderer.invoke 和 ipcMain.handle 进行进程间的通信
不推荐使用传统的单向通信 ipcRenderer.send 和 ipcMain.on
ipcRenderer.invoke 发送请求并等待响应, 返回一个 Promise
ipcRenderer.send 发送请求但不等待响应, 没有返回值
注
ipcMain.handle 在主进程中定义, 是接收者, 用于接收来自渲染进程的消息
ipcRenderer.invoke 在预加载脚本中调用, 是发送者, 用于向主进程发送消息
ipcRenderer.invoke(channel, data)
channel 是一个字符串,用于标识通信的通道,不同的通道名称可以调用不同的功能
发送者通过指定的 channel 发送数据,接收者通过监听相同的 channel 来接收数据
main.js
import { app, BrowserWindow, ipcMain } from "electron"
import url from 'url'
import path from 'path'
import os from 'os'
let __filename = url.fileURLToPath(import.meta.url)
let __dirname = path.dirname(__filename)
//console.log(os.version()) //内核版本
//console.log("邓瑞编程")
//创建窗口
const createWindow = () => {
const mainWindow = new BrowserWindow({
width: 1300, //设置窗口宽度(单位:像素)
height: 750, //设置窗口高度
icon: "resource/images/code.ico", //设置窗口图标
autoHideMenuBar:true, //隐藏菜单栏
//resizable: false, //禁止调整窗口大小
//x:0, //x表示窗口左上角的水平坐标(单位:像素)
//y:0, //y表示窗口左上角的垂直坐标
webPreferences: { //网页偏好设置
nodeIntegration: true, //允许在渲染进程中直接使用 Node.js API
contextIsolation: true, //启用上下文隔 (提高安全性)
preload: path.resolve(__dirname,"resource/preload/preload.mjs"), //预加载脚本
}
})
//mainWindow.loadURL("https://www.dengruicode.com") //加载指定的 url
mainWindow.loadFile("resource/renderer/views/index.html") //加载本地 html
//当尝试打开新窗口时, 阻止默认行为, 在当前窗口加载 url
mainWindow.webContents.setWindowOpenHandler(details =>{
mainWindow.loadURL(details.url)
return { action: 'deny' } //阻止默认行为
})
}
//当应用准备就绪后创建窗口
app.whenReady().then(() => {
createWindow()
})
//定义了一个处理函数, 用于响应名为 sendDataToMain 的异步调用
//当渲染进程通过 sendDataToMain 发起调用时, 处理函数会被触发
ipcMain.handle("sendDataToMain", (e,data) => {
console.log(data)
return data
})
preload.mjs
import os from 'os'
import { contextBridge, ipcRenderer } from "electron"
//console.log("preload.mjs")
contextBridge.exposeInMainWorld('DRAPI',{
url:"dengruicode.com",
version:os.version(),
sendDataToMain: async data => {
//向主进程发起一个名为 sendDataToMain 的异步调用, 并携带 data 数据
return await ipcRenderer.invoke('sendDataToMain',data)
}
})
index.js
//console.log("index.js", "dengruicode.com")
//console.log("index.js", window)
//渲染进程向主进程发送数据并获取返回值
DRAPI.sendDataToMain("dengruicode.com").then(data => {
console.log("data:", data)
}).catch(err => {
console.log("err:", err)
})