Electron 核心 API 全解析:从基础到实战场景
Electron 凭借丰富的 API 体系,让前端开发者能轻松调用系统级能力。本文将系统梳理 Electron 核心 API 的分类、使用场景及实战示例,帮你快速掌握从窗口管理到进程通信的全场景开发。
一、主进程核心 API(Main Process)
主进程是 Electron 应用的入口,负责管理应用生命周期、窗口创建及系统交互,运行在 Node.js 环境中。
1. app
:应用生命周期的“总控中心”
核心功能:控制应用启动、退出、路径管理等全局行为,是应用的“生命周期管家”。
常用方法与场景
方法/事件 | 作用 | 典型场景 |
---|---|---|
app.whenReady() | 等待应用初始化完成后执行回调 | 应用启动后创建主窗口 |
app.getPath(name) | 获取系统目录路径(如用户数据目录) | 存储应用配置、日志文件 |
app.quit() | 强制退出应用 | 响应“退出”菜单点击 |
app.on('window-all-closed') | 监听所有窗口关闭事件 | 非 macOS 系统自动退出应用 |
app.on('activate') | macOS 下点击 Dock 图标时触发 | 重新创建窗口(窗口全部关闭后) |
实战示例:基础生命周期管理
const { app, BrowserWindow } = require('electron')
const path = require('path')// 保存主窗口实例(避免被垃圾回收)
let mainWindow = null// 应用初始化完成后创建窗口
app.whenReady().then(() => {createMainWindow()// macOS 特有:Dock 图标点击时重建窗口app.on('activate', () => {if (BrowserWindow.getAllWindows().length === 0) {createMainWindow()}})
})// 所有窗口关闭时退出(Windows/Linux)
app.on('window-all-closed', () => {if (process.platform !== 'darwin') { // 排除 macOSapp.quit()}
})// 创建主窗口的工具函数
function createMainWindow() {mainWindow = new BrowserWindow({width: 800,height: 600,webPreferences: {preload: path.join(__dirname, 'preload.js')}})mainWindow.loadFile('index.html')
}// 获取系统路径示例(如用户数据目录)
const userDataPath = app.getPath('userData')
console.log('应用数据目录:', userDataPath) // 输出:C:\Users\用户名\AppData\Roaming\应用名(Windows)
2. BrowserWindow
:窗口管理的“基石”
核心功能:创建和控制应用窗口,支持自定义尺寸、样式及行为,是用户交互的载体。
核心配置与场景
配置项 | 作用 | 典型场景 |
---|---|---|
width /height | 窗口初始宽高 | 基础窗口尺寸设置 |
minWidth /minHeight | 窗口最小宽高 | 限制窗口缩放范围 |
frame: false | 禁用窗口边框(无边框窗口) | 自定义标题栏、沉浸式 UI |
fullscreen: true | 全屏显示 | 视频播放器、演示类应用 |
webPreferences | 网页渲染配置(核心安全配置) | 控制 Node 集成、预加载脚本 |
show: false | 初始隐藏窗口 | 窗口加载完成后再显示(避免白屏) |
实战示例 1:无边框窗口(带自定义标题栏)
// 创建无边框窗口
const borderlessWindow = new BrowserWindow({width: 900,height: 600,frame: false, // 禁用系统边框webPreferences: {preload: path.join(__dirname, 'preload.js')}
})// 加载页面
borderlessWindow.loadFile('borderless.html')// 无边框窗口的 HTML 中需配置可拖拽区域(CSS)
/*
.title-bar {-webkit-app-region: drag; /* 允许拖拽 */height: 32px;background: #333;color: white;
}
.title-bar-button {-webkit-app-region: no-drag; /* 按钮禁止拖拽 */margin: 4px;padding: 4px 8px;
}
*/
实战示例 2:窗口加载优化(避免白屏)
const splashWindow = new BrowserWindow({width: 400,height: 300,frame: false,transparent: true, // 透明背景alwaysOnTop: true // 始终置顶
})
splashWindow.loadFile('splash.html') // 加载启动屏// 主窗口配置
const mainWindow = new BrowserWindow({width: 1000,height: 700,show: false, // 初始隐藏webPreferences: { preload: path.join(__dirname, 'preload.js') }
})// 主窗口加载完成后显示并关闭启动屏
mainWindow.loadFile('index.html').then(() => {mainWindow.show() // 显示主窗口splashWindow.destroy() // 销毁启动屏
})
3. ipcMain
:主进程通信的“接收器”
核心功能:处理渲染进程发送的消息,支持同步/异步通信,是主进程与渲染进程交互的“桥梁”。
通信模式与场景
模式 | 方法 | 适用场景 |
---|---|---|
异步通信 | ipcMain.handle(channel, handler) | 耗时操作(文件读写、网络请求) |
同步通信 | ipcMain.on(channel, (event, data) => { ... }) | 简单数据获取(无阻塞风险) |
主进程主动推送 | webContents.send(channel, data) | 实时数据更新(如定时任务、系统事件) |
实战示例 1:异步文件读取(安全的进程通信)
// 主进程(main.js)
const { ipcMain, fs } = require('electron')
const path = require('path')// 注册异步通信通道:读取文件内容
ipcMain.handle('file:read', async (event, filePath) => {try {// 安全校验:限制只能读取应用数据目录下的文件const userDataPath = app.getPath('userData')if (!filePath.startsWith(userDataPath)) {throw new Error('无权访问该文件(仅允许读取应用数据目录)')}// 读取文件const content = fs.readFileSync(filePath, 'utf8')return { success: true, content }} catch (err) {return { success: false, error: err.message }}
})// 渲染进程通过预加载脚本调用(preload.js)
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {readFile: (filePath) => ipcRenderer.invoke('file:read', filePath)
})// 渲染进程(renderer.js)
async function loadFile() {const result = await window.electronAPI.readFile('/path/to/file.txt')if (result.success) {console.log('文件内容:', result.content)} else {alert('读取失败:' + result.error)}
}
实战示例 2:主进程主动推送实时数据
// 主进程:每秒推送当前时间
let mainWindow = new BrowserWindow(/* 配置 */)setInterval(() => {const time = new Date().toLocaleTimeString()// 通过 webContents 向渲染进程推送消息mainWindow.webContents.send('time:update', time)
}, 1000)// 预加载脚本暴露监听方法(preload.js)
contextBridge.exposeInMainWorld('electronAPI', {onTimeUpdate: (callback) => {ipcRenderer.on('time:update', (event, time) => callback(time))}
})// 渲染进程:显示实时时间
window.electronAPI.onTimeUpdate((time) => {document.getElementById('clock').textContent = `当前时间:${time}`
})
4. dialog
:系统对话框的“调用器”
核心功能:显示原生文件选择、消息提示、确认框等对话框,提供与系统一致的交互体验。
常用方法与场景
方法 | 作用 | 典型场景 |
---|---|---|
showOpenDialog() | 打开文件/目录选择对话框 | 导入文件、选择保存目录 |
showSaveDialog() | 打开文件保存对话框 | 导出数据、保存编辑内容 |
showMessageBox() | 显示消息提示框(支持警告、错误等类型) | 操作确认、错误提示、信息通知 |
实战示例 1:多类型文件选择器
const { dialog } = require('electron')// 打开支持多种格式的文件选择器
async function openMultiTypeFile() {const { filePaths, canceled } = await dialog.showOpenDialog({title: '选择媒体文件',defaultPath: app.getPath('documents'), // 默认打开“文档”目录properties: ['openFile', 'multiSelections'], // 支持多选文件filters: [ // 限制文件类型{ name: '图片', extensions: ['jpg', 'png', 'gif'] },{ name: '视频', extensions: ['mp4', 'mov', 'avi'] },{ name: '所有文件', extensions: ['*'] }]})if (!canceled) {console.log('选中的文件:', filePaths) // 输出选中的文件路径数组}
}
实战示例 2:带自定义按钮的消息框
const { dialog } = require('electron')// 显示带自定义按钮的确认框
async function showCustomMessageBox() {const { response, checkboxChecked } = await dialog.showMessageBox({type: 'question', // 对话框类型(info/warning/error/question)title: '操作确认',message: '是否删除该文件?',detail: '删除后将无法恢复,是否继续?',buttons: ['取消', '删除', '移到回收站'], // 自定义按钮defaultId: 0, // 默认选中第1个按钮(索引从0开始)checkboxLabel: '不再提示', // 复选框文本checkboxChecked: false // 复选框初始状态})// 处理用户选择switch (response) {case 0: // 取消console.log('用户取消操作')breakcase 1: // 删除console.log('用户选择直接删除')breakcase 2: // 移到回收站console.log('用户选择移到回收站')break}if (checkboxChecked) {console.log('用户勾选了“不再提示”')}
}
5. Menu
& Tray
:菜单与托盘的“构建器”
核心功能:创建应用菜单(顶部菜单栏/上下文菜单)和系统托盘图标,支持自定义交互逻辑。
应用场景
Menu
:创建顶部菜单栏(如文件、编辑、帮助)、右键上下文菜单;Tray
:实现应用最小化到系统托盘(后台运行),支持点击/右键交互。
实战示例:系统托盘与上下文菜单
const { Tray, Menu, BrowserWindow } = require('electron')
const path = require('path')function createTray(mainWindow) {// 创建托盘图标(推荐使用透明背景的PNG,尺寸32x32)const tray = new Tray(path.join(__dirname, 'tray-icon.png'))// 构建托盘右键菜单const contextMenu = Menu.buildFromTemplate([{ label: '显示窗口', click: () => {mainWindow.show() // 显示窗口mainWindow.focus() // 聚焦窗口}},{ label: '最小化到托盘', click: () => mainWindow.hide() // 隐藏窗口},{ type: 'separator' }, // 分隔线{ label: '退出', click: () => {mainWindow.destroy() // 销毁窗口app.quit() // 退出应用}}])// 配置托盘tray.setToolTip('我的Electron应用') // 鼠标悬停提示tray.setContextMenu(contextMenu) // 绑定右键菜单// 左键点击托盘图标:切换窗口显示/隐藏tray.on('click', () => {if (mainWindow.isVisible()) {mainWindow.hide()} else {mainWindow.show()}})return tray
}// 在创建主窗口后初始化托盘
let mainWindow = new BrowserWindow(/* 配置 */)
const tray = createTray(mainWindow)
二、渲染进程核心 API(Renderer Process)
渲染进程运行在 Chromium 浏览器环境中,负责 UI 渲染和用户交互,通过预加载脚本与主进程通信。
1. ipcRenderer
:渲染进程通信的“发送器”
核心功能:向主进程发送消息并接收响应,与 ipcMain
配合完成进程间通信。
常用方法与场景
方法 | 作用 | 典型场景 |
---|---|---|
ipcRenderer.invoke(channel, data) | 发送异步请求并等待响应 | 调用主进程API(文件操作、系统功能) |
ipcRenderer.send(channel, data) | 发送消息(无需响应) | 通知主进程状态变化(如用户操作) |
ipcRenderer.on(channel, listener) | 监听主进程发送的消息 | 接收实时数据(如定时更新、系统事件) |
实战示例:完整的进程通信流程
// 预加载脚本(preload.js):安全暴露通信API
const { contextBridge, ipcRenderer } = require('electron')contextBridge.exposeInMainWorld('electronAPI', {// 1. 异步请求-响应(如获取系统信息)getSystemInfo: () => ipcRenderer.invoke('system:info'),// 2. 单向通知(如用户操作日志)logUserAction: (action) => ipcRenderer.send('user:action', action),// 3. 监听主进程推送(如主题切换)onThemeChange: (callback) => {// 包装回调,避免直接暴露事件对象const wrapper = (event, theme) => callback(theme)ipcRenderer.on('theme:change', wrapper)// 返回清理函数(组件卸载时调用)return () => ipcRenderer.removeListener('theme:change', wrapper)}
})// 主进程(main.js):处理通信
const { ipcMain, systemPreferences } = require('electron')// 处理系统信息请求
ipcMain.handle('system:info', async () => {return {platform: process.platform, // 操作系统(win32/darwin/linux)theme: systemPreferences.getColor('window') === '#ffffff' ? 'light' : 'dark'}
})// 处理用户操作日志
ipcMain.on('user:action', (event, action) => {console.log('用户操作:', action) // 可写入日志文件
})// 主进程主动推送主题变化
function notifyThemeChange(theme) {mainWindow.webContents.send('theme:change', theme)
}// 渲染进程(Vue/React组件中):使用API
async function init() {// 获取系统信息const sysInfo = await window.electronAPI.getSystemInfo()console.log('系统信息:', sysInfo)// 记录用户操作window.electronAPI.logUserAction('打开设置页面')// 监听主题变化(并在组件卸载时清理)const cleanup = window.electronAPI.onThemeChange((theme) => {document.body.className = theme // 应用主题样式})// 组件卸载时调用清理return () => cleanup()
}
2. webFrame
:渲染行为的“控制器”
核心功能:控制网页渲染行为,如注入 CSS、修改缩放比例、执行脚本等。
常用方法与场景
方法 | 作用 | 典型场景 |
---|---|---|
webFrame.insertCSS(css) | 注入全局 CSS 样式 | 自定义全局主题、覆盖第三方样式 |
webFrame.setZoomFactor(factor) | 设置页面缩放比例 | 支持缩放功能的应用(如阅读器) |
webFrame.executeJavaScript(code) | 在页面上下文执行 JS 代码 | 动态修改页面内容、调用页面方法 |
实战示例:动态注入主题样式
// 渲染进程(通过预加载脚本暴露)
const { contextBridge, webFrame } = require('electron')contextBridge.exposeInMainWorld('themeAPI', {// 应用暗黑模式setDarkMode: () => {webFrame.insertCSS(`body { background: #1a1a1a !important; color: #fff !important; }.button { background: #333 !important; border: 1px solid #444 !important; }`)},// 重置默认样式resetStyle: () => {// 移除所有注入的CSS(需跟踪注入的样式ID)// 实际项目中可通过插入带ID的<style>标签,再移除实现}
})// 渲染进程调用
document.getElementById('darkModeBtn').addEventListener('click', () => {window.themeAPI.setDarkMode()
})
三、系统集成 API:与操作系统交互
Electron 提供了一系列与系统深度集成的 API,支持调用原生功能如剪贴板、全局快捷键、电源管理等。
1. shell
:系统操作的“快捷方式”
核心功能:调用系统默认程序处理文件、URL 等,如用默认浏览器打开网页、用默认播放器打开视频。
常用方法与场景
方法 | 作用 | 典型场景 |
---|---|---|
shell.openExternal(url) | 用默认应用打开 URL(网页/邮件等) | 打开帮助文档(网页)、发送邮件 |
shell.openPath(path) | 用默认应用打开文件/目录 | 查看下载的文件、打开日志目录 |
shell.trashItem(path) | 将文件移到回收站 | 安全删除文件(替代直接删除) |
shell.showItemInFolder(path) | 在文件管理器中显示文件 | 下载完成后定位文件位置 |
实战示例:文件操作集成
const { shell } = require('electron')
const path = require('path')// 1. 打开帮助网页
async function openHelpDoc() {try {await shell.openExternal('https://docs.example.com')} catch (err) {console.error('打开网页失败:', err)}
}// 2. 定位文件在资源管理器中的位置
async function showFileInFolder() {const filePath = path.join(app.getPath('downloads'), 'report.pdf')try {await shell.showItemInFolder(filePath)} catch (err) {console.error('文件不存在:', err)}
}// 3. 将文件移到回收站
async function deleteToTrash() {const filePath = 'path/to/file.txt'try {await shell.trashItem(filePath)console.log('文件已移到回收站')} catch (err) {console.error('删除失败:', err)}
}
2. clipboard
:剪贴板的“操作器”
核心功能:读写系统剪贴板,支持文本、HTML、图片等格式。
常用方法与场景
方法 | 作用 | 典型场景 |
---|---|---|
clipboard.writeText(text) | 写入文本到剪贴板 | 复制文本内容(如链接、代码) |
clipboard.readText() | 从剪贴板读取文本 | 粘贴文本到应用内 |
clipboard.writeImage(image) | 写入图片到剪贴板 | 复制截图、图片 |
clipboard.clear() | 清空剪贴板 | 敏感操作后清理剪贴板 |
实战示例:文本与图片剪贴板操作
const { clipboard, nativeImage } = require('electron')// 1. 复制文本
function copyTextToClipboard(text) {clipboard.writeText(text)console.log('已复制到剪贴板:', text)
}// 2. 粘贴文本
function pasteTextFromClipboard() {const text = clipboard.readText()console.log('剪贴板内容:', text)return text
}// 3. 复制图片(从文件)
async function copyImageToClipboard(imagePath) {const image = nativeImage.createFromPath(imagePath)clipboard.writeImage(image)console.log('已复制图片到剪贴板')
}
3. globalShortcut
:全局快捷键的“注册器”
核心功能:注册系统级快捷键,即使应用在后台也能响应(如截图工具的 Ctrl+Shift+A
)。
注意事项
- 快捷键需在应用就绪后注册,退出前注销;
- 避免与系统快捷键冲突(如
Ctrl+S
通常用于保存)。
实战示例:注册全局截图快捷键
const { app, globalShortcut, BrowserWindow } = require('electron')// 应用就绪后注册快捷键
app.whenReady().then(() => {// 注册 Ctrl+Shift+S 快捷键(Windows/Linux)const ret = globalShortcut.register('CommandOrControl+Shift+S', () => {console.log('触发截图快捷键')// 打开截图窗口const captureWindow = new BrowserWindow({width: 800,height: 600,frame: false,alwaysOnTop: true,webPreferences: { preload: path.join(__dirname, 'capture-preload.js') }})captureWindow.loadFile('screenshot.html')})if (!ret) {console.error('快捷键注册失败(可能已被占用)')}
})// 应用退出前注销所有快捷键
app.on('will-quit', () => {globalShortcut.unregisterAll() // 注销所有全局快捷键
})
四、安全最佳实践:API 使用的“红线”
Electron 应用的安全风险主要来自渲染进程对系统 API 的滥用,需严格遵循以下原则:
-
禁用
nodeIntegration
,启用contextIsolation
// 主进程窗口配置(必须遵守) new BrowserWindow({webPreferences: {nodeIntegration: false, // 禁用渲染进程直接访问Node.jscontextIsolation: true, // 启用上下文隔离(隔离渲染进程与主进程)preload: path.join(__dirname, 'preload.js') // 仅通过预加载脚本通信} })
-
通过
contextBridge
安全暴露 API
禁止直接暴露ipcRenderer
或主进程模块,仅暴露必要的方法:// 正确示例:暴露有限方法 contextBridge.exposeInMainWorld('electronAPI', {openFile: () => ipcRenderer.invoke('dialog:openFile') })// 错误示例:暴露完整ipcRenderer(风险) contextBridge.exposeInMainWorld('ipcRenderer', ipcRenderer) // ❌
-
限制
preload.js
的权限
预加载脚本应仅作为通信中介,避免包含复杂业务逻辑或敏感操作。 -
配置内容安全策略(CSP)
在 HTML 中限制资源加载,防止 XSS 攻击:<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';">
五、API 模块速查表
功能分类 | 核心模块/API | 关键方法/配置 |
---|---|---|
应用生命周期 | app | whenReady() 、quit() 、getPath() |
窗口管理 | BrowserWindow | 尺寸配置、loadFile() 、show() |
进程通信 | ipcMain /ipcRenderer | handle() 、invoke() 、send() |
系统对话框 | dialog | showOpenDialog() 、showMessageBox() |
菜单与托盘 | Menu /Tray | buildFromTemplate() 、setContextMenu() |
系统集成 | shell /clipboard /globalShortcut | openExternal() 、writeText() 、register() |
渲染控制 | webFrame | insertCSS() 、setZoomFactor() |
通过合理组合这些 API,可实现从简单窗口到复杂系统工具的全场景应用开发。建议结合 Electron 官方文档 深入学习每个模块的细节,同时始终将安全最佳实践贯穿开发全过程。