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 官方文檔 深入學習每個模塊的細節,同時始終將安全最佳實踐貫穿開發全過程。