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 图标时触发 | 重新创建窗口(窗口全部关闭后) |
实战示例:基础生命周期管理
javascript
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') { // 排除 macOS
app.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:无边框窗口(带自定义标题栏)
javascript
// 创建无边框窗口
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:窗口加载优化(避免白屏)
javascript
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:异步文件读取(安全的进程通信)
javascript
// 主进程(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:主进程主动推送实时数据
javascript
// 主进程:每秒推送当前时间
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:多类型文件选择器
javascript
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:带自定义按钮的消息框
javascript
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('用户取消操作')
break
case 1: // 删除
console.log('用户选择直接删除')
break
case 2: // 移到回收站
console.log('用户选择移到回收站')
break
}
if (checkboxChecked) {
console.log('用户勾选了"不再提示"')
}
}
5. Menu
& Tray
:菜单与托盘的"构建器"
核心功能:创建应用菜单(顶部菜单栏/上下文菜单)和系统托盘图标,支持自定义交互逻辑。
应用场景
Menu
:创建顶部菜单栏(如文件、编辑、帮助)、右键上下文菜单;Tray
:实现应用最小化到系统托盘(后台运行),支持点击/右键交互。
实战示例:系统托盘与上下文菜单
javascript
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) |
监听主进程发送的消息 | 接收实时数据(如定时更新、系统事件) |
实战示例:完整的进程通信流程
javascript
// 预加载脚本(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 代码 | 动态修改页面内容、调用页面方法 |
实战示例:动态注入主题样式
javascript
// 渲染进程(通过预加载脚本暴露)
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) |
在文件管理器中显示文件 | 下载完成后定位文件位置 |
实战示例:文件操作集成
javascript
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() |
清空剪贴板 | 敏感操作后清理剪贴板 |
实战示例:文本与图片剪贴板操作
javascript
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
通常用于保存)。
实战示例:注册全局截图快捷键
javascript
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
javascript// 主进程窗口配置(必须遵守) new BrowserWindow({ webPreferences: { nodeIntegration: false, // 禁用渲染进程直接访问Node.js contextIsolation: true, // 启用上下文隔离(隔离渲染进程与主进程) preload: path.join(__dirname, 'preload.js') // 仅通过预加载脚本通信 } })
-
通过
contextBridge
安全暴露 API禁止直接暴露
ipcRenderer
或主进程模块,仅暴露必要的方法:javascript// 正确示例:暴露有限方法 contextBridge.exposeInMainWorld('electronAPI', { openFile: () => ipcRenderer.invoke('dialog:openFile') }) // 错误示例:暴露完整ipcRenderer(风险) contextBridge.exposeInMainWorld('ipcRenderer', ipcRenderer) // ❌
-
限制
preload.js
的权限预加载脚本应仅作为通信中介,避免包含复杂业务逻辑或敏感操作。
-
配置内容安全策略(CSP)
在 HTML 中限制资源加载,防止 XSS 攻击:
html<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 官方文档 深入学习每个模块的细节,同时始终将安全最佳实践贯穿开发全过程。