Skip to Content
Nextra 4.0 is released 🎉

Electron 学习指南

Electron 是一个使用 JavaScript、HTML 和 CSS 构建跨平台桌面应用程序的框架。它将 Chromium 和 Node.js 合并到一个运行时环境中,让开发者可以使用 Web 技术构建原生应用。

🚀 快速开始

创建 Electron 项目

# 创建新项目 mkdir my-electron-app cd my-electron-app npm init -y # 安装 Electron npm install electron --save-dev # 安装开发工具 npm install electron-builder --save-dev

基本项目结构

my-electron-app/ ├── package.json ├── main.js # 主进程 ├── preload.js # 预加载脚本 ├── renderer.js # 渲染进程 ├── index.html # 主窗口 └── src/ ├── assets/ └── styles/

📚 核心概念

主进程和渲染进程

Electron 应用由两个进程组成:

// main.js - 主进程 const { app, BrowserWindow } = require('electron'); const path = require('path'); function createWindow() { const mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, 'preload.js') } }); mainWindow.loadFile('index.html'); } app.whenReady().then(createWindow); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } });
// preload.js - 预加载脚本 const { contextBridge, ipcRenderer } = require('electron'); contextBridge.exposeInMainWorld('electronAPI', { sendMessage: (message) => ipcRenderer.send('message', message), onMessage: (callback) => ipcRenderer.on('message', callback) });
<!-- index.html - 渲染进程 --> <!DOCTYPE html> <html> <head> <title>Electron App</title> </head> <body> <h1>Hello Electron!</h1> <button id="sendBtn">Send Message</button> <script src="renderer.js"></script> </body> </html>
// renderer.js - 渲染进程脚本 document.getElementById('sendBtn').addEventListener('click', () => { window.electronAPI.sendMessage('Hello from renderer!'); }); window.electronAPI.onMessage((event, message) => { console.log('Received:', message); });

⚡ 进程间通信 (IPC)

主进程到渲染进程

// main.js const { ipcMain, BrowserWindow } = require('electron'); ipcMain.handle('get-data', async () => { return { message: 'Data from main process' }; }); ipcMain.on('send-to-renderer', (event, data) => { // 发送到所有渲染进程 BrowserWindow.getAllWindows().forEach(window => { window.webContents.send('message-from-main', data); }); });

渲染进程到主进程

// preload.js contextBridge.exposeInMainWorld('electronAPI', { getData: () => ipcRenderer.invoke('get-data'), sendToMain: (data) => ipcRenderer.send('send-to-main', data), onMessageFromMain: (callback) => ipcRenderer.on('message-from-main', callback) });
// renderer.js // 调用主进程方法 window.electronAPI.getData().then(data => { console.log(data); }); // 发送消息到主进程 window.electronAPI.sendToMain('Hello from renderer'); // 监听主进程消息 window.electronAPI.onMessageFromMain((event, data) => { console.log('From main:', data); });

🎯 窗口管理

创建不同类型的窗口

// main.js const { BrowserWindow, BrowserView } = require('electron'); function createMainWindow() { const mainWindow = new BrowserWindow({ width: 1200, height: 800, show: false, // 先隐藏,加载完成后再显示 webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, 'preload.js') } }); mainWindow.loadFile('index.html'); mainWindow.once('ready-to-show', () => { mainWindow.show(); }); } function createModalWindow(parent) { const modal = new BrowserWindow({ width: 600, height: 400, parent: parent, modal: true, webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, 'preload.js') } }); modal.loadFile('modal.html'); }

窗口状态管理

// main.js let mainWindow; function createWindow() { mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, 'preload.js') } }); // 保存窗口状态 mainWindow.on('close', () => { const bounds = mainWindow.getBounds(); // 保存到配置文件 saveWindowState(bounds); }); // 恢复窗口状态 const savedBounds = loadWindowState(); if (savedBounds) { mainWindow.setBounds(savedBounds); } }

🔧 应用生命周期

应用事件处理

// main.js const { app } = require('electron'); // 应用准备就绪 app.whenReady().then(() => { createWindow(); // macOS 应用激活 app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } }); }); // 所有窗口关闭 app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } }); // 应用即将退出 app.on('before-quit', () => { // 保存数据 saveApplicationData(); }); // 应用退出 app.on('quit', () => { // 清理资源 cleanup(); });

📦 原生功能集成

系统托盘

// main.js const { Tray, Menu } = require('electron'); const path = require('path'); let tray; function createTray() { tray = new Tray(path.join(__dirname, 'assets/icon.png')); const contextMenu = Menu.buildFromTemplate([ { label: '显示应用', click: () => mainWindow.show() }, { label: '隐藏应用', click: () => mainWindow.hide() }, { type: 'separator' }, { label: '退出', click: () => app.quit() } ]); tray.setToolTip('我的 Electron 应用'); tray.setContextMenu(contextMenu); tray.on('click', () => { mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show(); }); }

文件系统操作

// main.js const { ipcMain, dialog } = require('electron'); const fs = require('fs').promises; ipcMain.handle('open-file', async () => { const result = await dialog.showOpenDialog({ properties: ['openFile'], filters: [ { name: '文本文件', extensions: ['txt'] }, { name: '所有文件', extensions: ['*'] } ] }); if (!result.canceled) { const filePath = result.filePaths[0]; const content = await fs.readFile(filePath, 'utf8'); return { filePath, content }; } }); ipcMain.handle('save-file', async (event, content) => { const result = await dialog.showSaveDialog({ filters: [ { name: '文本文件', extensions: ['txt'] } ] }); if (!result.canceled) { await fs.writeFile(result.filePath, content); return result.filePath; } });

系统通知

// main.js const { Notification } = require('electron'); function showNotification(title, body) { new Notification({ title: title, body: body, icon: path.join(__dirname, 'assets/icon.png') }).show(); } ipcMain.handle('show-notification', (event, title, body) => { showNotification(title, body); });

🛠️ 开发工具

开发者工具

// main.js function createWindow() { const mainWindow = new BrowserWindow({ // ... 其他配置 }); // 开发环境打开开发者工具 if (process.env.NODE_ENV === 'development') { mainWindow.webContents.openDevTools(); } }

热重载

// main.js if (process.env.NODE_ENV === 'development') { require('electron-reload')(__dirname, { electron: path.join(__dirname, 'node_modules', '.bin', 'electron') }); }

📦 打包和分发

使用 electron-builder

// package.json { "name": "my-electron-app", "version": "1.0.0", "main": "main.js", "scripts": { "start": "electron .", "build": "electron-builder", "build:win": "electron-builder --win", "build:mac": "electron-builder --mac", "build:linux": "electron-builder --linux" }, "build": { "appId": "com.example.myapp", "productName": "我的应用", "directories": { "output": "dist" }, "files": [ "main.js", "preload.js", "renderer.js", "index.html", "assets/**/*" ], "win": { "target": "nsis", "icon": "assets/icon.ico" }, "mac": { "target": "dmg", "icon": "assets/icon.icns" }, "linux": { "target": "AppImage", "icon": "assets/icon.png" } } }

自动更新

// main.js const { autoUpdater } = require('electron-updater'); function setupAutoUpdater() { autoUpdater.checkForUpdatesAndNotify(); autoUpdater.on('update-available', () => { console.log('更新可用'); }); autoUpdater.on('update-downloaded', () => { console.log('更新已下载'); }); autoUpdater.on('error', (err) => { console.error('更新错误:', err); }); }

🔒 安全最佳实践

安全配置

// main.js function createWindow() { const mainWindow = new BrowserWindow({ webPreferences: { nodeIntegration: false, // 禁用 Node.js 集成 contextIsolation: true, // 启用上下文隔离 enableRemoteModule: false, // 禁用远程模块 preload: path.join(__dirname, 'preload.js') } }); }

CSP 配置

<!-- index.html --> <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline';">

📖 学习资源

官方文档

实用工具和库

  • electron-builder: 应用打包工具
  • electron-updater: 自动更新
  • electron-store: 数据持久化
  • electron-log: 日志记录
  • electron-devtools-installer: 开发者工具安装

🔍 调试工具

  • Electron DevTools: 内置开发者工具
  • Spectron: Electron 应用测试框架
  • electron-debug: 调试工具

最后更新: 2024年

最近更新:12/9/2025, 2:17:54 AM