主进程固然拥有最完整的系统能力,但在日常开发中,渲染进程同样需要直接调用一些不涉及高风险操作的 API。Electron 提供了一系列可在渲染进程安全使用的模块,只要通过 contextBridge 正确暴露,就能在界面脚本中像调用普通函数一样使用它们,既方便又不会破坏安全隔离。
8.4.1 shell 模块
shell 模块专门处理与操作系统桌面集成相关的任务,最常用的功能有:
- 在用户默认浏览器中打开外部链接;
- 在文件管理器中显示某个文件或文件夹;
- 将文件移至回收站。
这些操作不涉及读写用户文件的敏感内容,非常适合直接暴露给渲染进程。
在 preload 中暴露
// preload.js
const { contextBridge, shell } = require('electron');
contextBridge.exposeInMainWorld('shellAPI', {
openExternal: (url) => shell.openExternal(url),
showItemInFolder: (filePath) => shell.showItemInFolder(filePath),
});
渲染进程使用
// 打开外部链接
window.shellAPI.openExternal('https://example.com');
// 在文件管理器中定位文件
window.shellAPI.showItemInFolder('C:\\Users\\example\\file.txt');
注意事项:shell.openExternal 在处理用户提供的链接时,务必先校验协议(只允许 http:、https: 等),防止恶意程序打开本地可执行文件。
8.4.2 clipboard 模块
clipboard 模块让应用可以读写系统剪贴板中的文本、HTML 甚至图片内容。它通常在以下场景中使用:
- 实现“复制到剪贴板”功能;
- 粘贴内容到应用内;
- 处理快捷键操作(Ctrl+C / Ctrl+V)。
同样,通过 preload 暴露必要的读写方法即可。
在 preload 中暴露
// preload.js
const { contextBridge, clipboard } = require('electron');
contextBridge.exposeInMainWorld('clipboardAPI', {
writeText: (text) => clipboard.writeText(text),
readText: () => clipboard.readText(),
});
渲染进程使用
// 复制文本
window.clipboardAPI.writeText('已复制的内容');
// 读取剪贴板(通常用于“粘贴”操作)
const clipboardText = window.clipboardAPI.readText();
如果需要在应用中监视剪贴板变化,可以让主进程通过 clipboard.on('changed') 监听,再通过 IPC 通知渲染进程。直接将监听器暴露给渲染进程可能引入不必要的复杂性。
8.4.3 Notification 通知
桌面通知是提高用户体验的重要一环。HTML5 标准提供的 Notification API 本身就可以在 Electron 渲染进程中使用,而且 Electron 对其进行了增强,使其外观与系统原生通知一致。因此,我们甚至不需要通过 preload 暴露任何额外模块,直接使用浏览器内置的 Notification 构造函数即可。
渲染进程直接使用
// 发送一条简单的系统通知
new Notification('任务完成', {
body: '文件已成功保存到桌面',
});
// 带上点击事件的用法
const notify = new Notification('更新提示', {
body: '新版本已下载,点击重启',
});
notify.onclick = () => {
// 通知被点击时执行操作,例如窗口置顶
console.log('通知被点击');
};
这种方式完全在渲染进程沙箱内运行,安全且直观。需要注意:Windows 系统要求应用打包后有相应的 AppUserModelID 才能正常显示通知,使用 electron-builder 等工具时一般会自动处理。
如果希望在主进程统一管理通知(比如应用在后台时也能弹出通知),可以在 preload 中暴露一个 IPC 通道,由主进程调用 Notification 模块(const { Notification } = require('electron')),但多数情况下渲染进程直接使用就已经足够。
8.4.4 其他常用渲染端能力
除了上述三个高频模块,下列能力也经常通过 preload 暴露给渲染进程:
- nativeTheme:获取当前系统主题(浅色/深色),并监听主题变化,让应用界面实时跟随系统设置。
- screen:获取屏幕尺寸、显示器信息,用于多屏布局或窗口适配。
- ipcRenderer:核心通信通道,几乎所有需要主进程参与的功能都必须通过
ipcRenderer.invoke或send来实现。
示例:暴露主题跟随能力
// preload.js
const { contextBridge, nativeTheme } = require('electron');
contextBridge.exposeInMainWorld('themeAPI', {
getTheme: () => nativeTheme.shouldUseDarkColors ? 'dark' : 'light',
onThemeChanged: (callback) => {
nativeTheme.on('updated', () => {
callback(nativeTheme.shouldUseDarkColors ? 'dark' : 'light');
});
},
});
// 渲染进程
window.themeAPI.onThemeChanged((theme) => {
document.body.className = theme;
});
8.4.5 安全原则提醒
无论暴露哪一个模块,请始终坚持最小权限原则:
- 只暴露渲染进程真正需要的具体方法,而不是整个模块对象(例如
clipboard: clipboard这种写法会将所有读写方法暴露,不推荐)。 - 对用户提供的数据进行校验,避免直接传入
shell.openExternal这类方法。 - 使用
contextBridge并保持contextIsolation: true(默认),不要直接在渲染进程中require('electron')。
通过上述封装,渲染进程既可以获得灵活的桌面交互能力,又牢牢守住了应用的安全底线。在下一节中,我们将进一步学习如何将这些能力与 IPC 结合起来,打造流畅的主进程-渲染进程协作体验。