Electron 的主进程是一个拥有着完全操作系统访问权限的 Node.js 环境。 除了 Electron 模组 之外,您也可以访问 Node.js 内置模块 和所有通过 npm 安装的包。 另一方面,出于安全原因,渲染进程默认跑在网页页面上,而并非 Node.js里。
为了将 Electron 的不同类型的进程桥接在一起,我们需要使用被称为预加载的特殊脚本。
使用预加载脚本来增强渲染器
BrowserWindow 的预加载脚本运行在具有 HTML DOM 和 Node.js、Electron API 的有限子集访问权限的环境中。
预加载脚本在渲染器加载网页之前注入。 如果你想为渲染器添加需要特殊权限的功能,可以通过 contextBridge 接口定义 全局对象。
preload.js
const { contextBridge } = require('electron/renderer')contextBridge.exposeInMainWorld('versions', {node: () => process.versions.node,chrome: () => process.versions.chrome,electron: () => process.versions.electron})
render.js
const information = document.getElementById('info')information.innerText = `This app is using Chrome (v${window.versions.chrome()}), Node.js (v${window.versions.node()}), and Electron (v${window.versions.electron()})`
在进程之间通信
我们之前提到,Electron 的主进程和渲染进程有着清楚的分工并且不可互换。 这代表着无论是从渲染进程直接访问 Node.js 接口,亦或者是从主进程访问 HTML 文档对象模型 (DOM),都是不可能的。
解决这一问题的方法是使用进程间通信 (IPC)。可以使用 Electron 的 ipcMain 模块和 ipcRenderer 模块来进行进程间通信。 为了从你的网页向主进程发送消息,你可以使用 ipcMain.handle 设置一个主进程处理程序(handler),然后在预处理脚本中暴露一个被称为 ipcRenderer.invoke 的函数来触发该处理程序(handler)。
preload.js
const { contextBridge, ipcRenderer } = require('electron')contextBridge.exposeInMainWorld('versions', {node: () => process.versions.node,chrome: () => process.versions.chrome,electron: () => process.versions.electron,ping: () => ipcRenderer.invoke('ping')// 除函数之外,我们也可以暴露变量})
main.js
const { app, BrowserWindow, ipcMain } = require('electron/main')const path = require('node:path')const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600,webPreferences: {preload: path.join(__dirname, 'preload.js')}})win.loadFile('index.html')}app.whenReady().then(() => {ipcMain.handle('ping', () => 'pong')createWindow()})
将发送器与接收器设置完成之后,现在你可以将信息通过刚刚定义的 ‘ping’ 通道从渲染器发送至主进程当中。
render.js
const func = async () => {const response = await window.versions.ping()console.log(response) // 打印 'pong'}func()
