外观
Electron BrowserWindow
Electron BrowserWindow 是创建和控制浏览器窗口的核心模块,它提供了丰富的 API 来创建原生桌面应用程序窗口。每个 BrowserWindow 实例都运行在独立的渲染进程中,可以加载本地 HTML 文件或远程 URL,并支持高度自定义的窗口行为和外观。
BrowserWindow 基础架构
BrowserWindow 是 Electron 应用的用户界面载体,它将 Chromium 的渲染能力与原生窗口控制相结合,形成统一的跨平台窗口管理解决方案。
BrowserWindow 实例架构:
BrowserWindow 实例
|
+-- 原生窗口控件 (Native Window)
| |
| +-- 窗口边框和标题栏
| +-- 最小化/最大化/关闭按钮
| +-- 系统菜单和托盘
|
+-- WebContents 实例
| |
| +-- Chromium 渲染引擎
| +-- 页面加载和导航控制
| +-- 开发者工具集成
|
+-- 事件系统
|
+-- 窗口生命周期事件
+-- 用户交互事件
+-- Web 内容事件窗口创建与基础配置
基础窗口创建
创建基本的 BrowserWindow 实例只需要几行代码:
javascript
// main.js
import { BrowserWindow } from 'electron';
// 创建基础窗口
const createBasicWindow = () => {
const mainWindow = new BrowserWindow({
width: 1200,
height: 800,
show: false, // 初始不显示,避免视觉闪烁
});
// 窗口准备好后显示
mainWindow.once('ready-to-show', () => {
mainWindow.show();
mainWindow.focus();
});
// 加载应用内容
mainWindow.loadFile('index.html');
return mainWindow;
};完整配置选项
BrowserWindow 支持丰富的配置选项,涵盖外观、行为和安全各个方面:
javascript
// main.js
import { BrowserWindow } from 'electron';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const createConfiguredWindow = () => {
const window = new BrowserWindow({
// 基础尺寸配置
width: 1200,
height: 800,
minWidth: 800,
minHeight: 600,
maxWidth: 1600,
maxHeight: 1200,
// 窗口位置
x: 100,
y: 100,
center: true, // 在屏幕居中
// 窗口外观
title: '我的 Electron 应用',
icon: path.join(__dirname, 'assets/icon.png'),
show: false,
frame: true, // 是否显示窗口边框
transparent: false, // 透明窗口
titleBarStyle: 'default', // 'default' | 'hidden' | 'hiddenInset' | 'customButtonsOnHover'
thickFrame: true, // Windows 厚边框
vibrancy: 'under-window', // macOS 毛玻璃效果
// 窗口行为
resizable: true,
movable: true,
minimizable: true,
maximizable: true,
closable: true,
focusable: true,
alwaysOnTop: false,
fullscreenable: true,
skipTaskbar: false,
kiosk: false, // 自助服务模式
// 安全配置
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
enableRemoteModule: false,
preload: path.join(__dirname, 'preload.js'),
webSecurity: true,
allowRunningInsecureContent: false,
experimentalFeatures: false,
webgl: true,
plugins: true,
scrollBounce: true, // macOS 弹性滚动
},
// 平台特定配置
...(process.platform === 'darwin' && {
titleBarStyle: 'hiddenInset',
trafficLightPosition: { x: 16, y: 16 }
}),
...(process.platform === 'win32' && {
thickFrame: true,
titleBarStyle: 'hidden'
}),
...(process.platform === 'linux' && {
icon: path.join(__dirname, 'assets/icon.png')
})
});
return window;
};窗口生命周期管理
窗口状态控制
BrowserWindow 提供完整的方法来控制窗口状态和行为:
javascript
// main.js
import { BrowserWindow, ipcMain } from 'electron';
class WindowManager {
constructor() {
this.windows = new Map();
this.setupWindowControls();
}
setupWindowControls() {
// IPC 控制窗口
ipcMain.handle('window:minimize', (event) => {
const window = BrowserWindow.fromWebContents(event.sender);
window.minimize();
});
ipcMain.handle('window:maximize', (event) => {
const window = BrowserWindow.fromWebContents(event.sender);
if (window.isMaximized()) {
window.unmaximize();
} else {
window.maximize();
}
});
ipcMain.handle('window:close', (event) => {
const window = BrowserWindow.fromWebContents(event.sender);
window.close();
});
ipcMain.handle('window:fullscreen', (event) => {
const window = BrowserWindow.fromWebContents(event.sender);
window.setFullScreen(!window.isFullScreen());
});
}
createWindow(id, options = {}) {
const window = new BrowserWindow({
width: 1200,
height: 800,
show: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js'),
},
...options
});
this.windows.set(id, window);
// 窗口事件处理
window.on('closed', () => {
this.windows.delete(id);
});
window.on('focus', () => {
this.onWindowFocus(id);
});
window.on('blur', () => {
this.onWindowBlur(id);
});
return window;
}
onWindowFocus(windowId) {
console.log(`窗口 ${windowId} 获得焦点`);
// 更新应用状态,比如菜单栏
}
onWindowBlur(windowId) {
console.log(`窗口 ${windowId} 失去焦点`);
}
getWindow(id) {
return this.windows.get(id);
}
closeAllWindows() {
this.windows.forEach((window) => {
if (!window.isDestroyed()) {
window.close();
}
});
this.windows.clear();
}
}多窗口管理
复杂的应用通常需要管理多个窗口:
javascript
// main.js
import { BrowserWindow, screen } from 'electron';
class MultiWindowManager {
constructor() {
this.windows = new Map();
this.windowStates = new Map();
}
// 创建主窗口
createMainWindow() {
const mainWindow = this.createWindow('main', {
width: 1200,
height: 800,
webPreferences: {
preload: path.join(__dirname, 'preload-main.js')
}
});
mainWindow.loadFile('main.html');
return mainWindow;
}
// 创建设置窗口
createSettingsWindow() {
const mainWindow = this.getWindow('main');
const settingsWindow = this.createWindow('settings', {
width: 600,
height: 400,
parent: mainWindow,
modal: true,
resizable: false,
webPreferences: {
preload: path.join(__dirname, 'preload-settings.js')
}
});
settingsWindow.loadFile('settings.html');
return settingsWindow;
}
// 创建工具窗口
createToolWindow() {
const { workArea } = screen.getPrimaryDisplay();
const toolWindow = this.createWindow('tool', {
width: 300,
height: 200,
x: workArea.width - 320,
y: workArea.height - 220,
alwaysOnTop: true,
skipTaskbar: true,
resizable: false,
webPreferences: {
preload: path.join(__dirname, 'preload-tool.js')
}
});
toolWindow.loadFile('tool.html');
return toolWindow;
}
// 保存窗口状态
saveWindowState(windowId, state) {
this.windowStates.set(windowId, {
...state,
timestamp: Date.now()
});
}
// 恢复窗口状态
restoreWindowState(windowId) {
return this.windowStates.get(windowId) || null;
}
}高级窗口特性
无边框窗口与自定义标题栏
创建无边框窗口并实现自定义标题栏:
javascript
// main.js
import { BrowserWindow } from 'electron';
const createFramelessWindow = () => {
const window = new BrowserWindow({
width: 1200,
height: 800,
frame: false, // 无边框
titleBarStyle: 'hidden', // 隐藏标题栏
backgroundColor: '#2e3440',
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
}
});
// 自定义窗口控制
window.on('maximize', () => {
window.webContents.send('window:maximized');
});
window.on('unmaximize', () => {
window.webContents.send('window:unmaximized');
});
window.loadFile('frameless.html');
return window;
};javascript
// preload.js
import { contextBridge, ipcRenderer } from 'electron';
contextBridge.exposeInMainWorld('electronAPI', {
windowControl: {
minimize: () => ipcRenderer.send('window:minimize'),
maximize: () => ipcRenderer.send('window:maximize'),
close: () => ipcRenderer.send('window:close'),
isMaximized: () => ipcRenderer.invoke('window:isMaximized'),
onMaximized: (callback) => ipcRenderer.on('window:maximized', callback),
onUnmaximized: (callback) => ipcRenderer.on('window:unmaximized', callback)
}
});透明窗口与视觉效果
创建具有视觉效果的透明窗口:
javascript
// main.js
import { BrowserWindow } from 'electron';
const createVisualEffectWindow = () => {
const window = new BrowserWindow({
width: 800,
height: 600,
transparent: true, // 透明背景
frame: false,
resizable: false,
alwaysOnTop: true,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js'),
backgroundThrottling: false
},
...(process.platform === 'darwin' && {
vibrancy: 'ultra-dark', // macOS 毛玻璃效果
visualEffectState: 'active'
})
});
// 设置窗口形状
window.setShape([
{ x: 0, y: 0, width: 800, height: 600, borderRadius: 20 }
]);
window.loadFile('visual.html');
return window;
};多显示器支持
处理多显示器环境的窗口管理:
javascript
// main.js
import { BrowserWindow, screen } from 'electron';
class MultiDisplayManager {
constructor() {
this.displays = screen.getAllDisplays();
}
// 在指定显示器创建窗口
createWindowOnDisplay(displayIndex, options = {}) {
const display = this.displays[displayIndex];
if (!display) {
throw new Error(`显示器 ${displayIndex} 不存在`);
}
const { workArea } = display;
const window = new BrowserWindow({
x: workArea.x + 50,
y: workArea.y + 50,
width: workArea.width - 100,
height: workArea.height - 100,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
},
...options
});
// 监听显示器变化
screen.on('display-added', this.handleDisplayChange.bind(this));
screen.on('display-removed', this.handleDisplayChange.bind(this));
screen.on('display-metrics-changed', this.handleDisplayChange.bind(this));
return window;
}
handleDisplayChange() {
this.displays = screen.getAllDisplays();
// 更新窗口位置和大小
this.updateWindowPositions();
}
updateWindowPositions() {
// 根据新的显示器配置更新所有窗口
BrowserWindow.getAllWindows().forEach((window, index) => {
const display = this.displays[index % this.displays.length];
if (display && !window.isDestroyed()) {
const { workArea } = display;
window.setBounds({
x: workArea.x + 50,
y: workArea.y + 50,
width: Math.min(window.getBounds().width, workArea.width - 100),
height: Math.min(window.getBounds().height, workArea.height - 100)
});
}
});
}
// 获取窗口所在的显示器
getWindowDisplay(window) {
const bounds = window.getBounds();
return screen.getDisplayNearestPoint({
x: bounds.x + bounds.width / 2,
y: bounds.y + bounds.height / 2
});
}
}WebContents 控制与内容管理
页面加载与导航控制
javascript
// main.js
import { BrowserWindow, session } from 'electron';
const createControlledWindow = () => {
const window = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
}
});
// 页面加载事件
window.webContents.on('did-start-loading', () => {
console.log('开始加载页面');
window.webContents.send('loading:start');
});
window.webContents.on('did-finish-load', () => {
console.log('页面加载完成');
window.webContents.send('loading:finish');
});
window.webContents.on('did-fail-load', (event, errorCode, errorDescription) => {
console.error('页面加载失败:', errorDescription);
window.webContents.send('loading:error', { errorCode, errorDescription });
});
// 导航控制
window.webContents.on('will-navigate', (event, navigationUrl) => {
console.log('即将导航到:', navigationUrl);
// 阻止外部链接在应用内打开
const parsedUrl = new URL(navigationUrl);
if (parsedUrl.origin !== 'file://') {
event.preventDefault();
require('electron').shell.openExternal(navigationUrl);
}
});
// 新窗口控制
window.webContents.setWindowOpenHandler(({ url }) => {
// 所有新窗口都在外部浏览器打开
require('electron').shell.openExternal(url);
return { action: 'deny' };
});
return window;
};开发者工具集成
javascript
// main.js
import { BrowserWindow } from 'electron';
class DevToolsManager {
constructor(window) {
this.window = window;
this.setupDevTools();
}
setupDevTools() {
// 开发环境自动打开开发者工具
if (process.env.NODE_ENV === 'development') {
this.window.webContents.openDevTools();
}
// 监听开发者工具事件
this.window.webContents.on('devtools-opened', () => {
console.log('开发者工具已打开');
this.window.webContents.send('devtools:changed', true);
});
this.window.webContents.on('devtools-closed', () => {
console.log('开发者工具已关闭');
this.window.webContents.send('devtools:changed', false);
});
// 添加快捷键
this.window.webContents.on('before-input-event', (event, input) => {
if (input.key === 'F12' || (input.control && input.key === 'i')) {
event.preventDefault();
this.toggleDevTools();
}
});
}
toggleDevTools() {
if (this.window.webContents.isDevToolsOpened()) {
this.window.webContents.closeDevTools();
} else {
this.window.webContents.openDevTools();
}
}
// 检查元素模式
inspectElement(x, y) {
this.window.webContents.inspectElement(x, y);
if (!this.window.webContents.isDevToolsOpened()) {
this.window.webContents.openDevTools();
}
}
}性能优化与最佳实践
内存管理与性能优化
javascript
// main.js
import { BrowserWindow, app } from 'electron';
class OptimizedWindowManager {
constructor() {
this.windows = new Map();
this.setupPerformanceOptimizations();
}
setupPerformanceOptimizations() {
// 应用级别性能优化
app.commandLine.appendSwitch('--disable-background-timer-throttling');
app.commandLine.appendSwitch('--disable-renderer-backgrounding');
// 内存警告处理
app.on('memory-warning', () => {
this.cleanupMemory();
});
}
createOptimizedWindow(id, options = {}) {
const window = new BrowserWindow({
width: 1200,
height: 800,
show: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js'),
backgroundThrottling: false, // 防止后台节流
webSecurity: true,
allowRunningInsecureContent: false,
...options.webPreferences
},
...options
});
this.windows.set(id, window);
// 性能优化事件
window.on('ready-to-show', () => {
window.show();
this.initializeWindowPerformance(window);
});
window.on('focus', () => {
this.onWindowFocusOptimizations(window);
});
window.on('blur', () => {
this.onWindowBlurOptimizations(window);
});
// 内存使用监控
setInterval(() => {
this.monitorWindowMemory(window);
}, 30000);
return window;
}
initializeWindowPerformance(window) {
// 启用硬件加速
window.webContents.setBackgroundThrottling(false);
// 设置帧率
window.webContents.setFrameRate(60);
}
onWindowFocusOptimizations(window) {
// 恢复高性能模式
window.webContents.setBackgroundThrottling(false);
window.webContents.setFrameRate(60);
}
onWindowBlurOptimizations(window) {
// 降低非活动窗口的资源使用
if (!window.isFocused()) {
window.webContents.setFrameRate(30);
}
}
monitorWindowMemory(window) {
const memoryInfo = window.webContents.getProcessMemoryInfo();
if (memoryInfo.privateBytes > 500 * 1024 * 1024) { // 500MB
console.warn('窗口内存使用过高:', memoryInfo.privateBytes);
this.triggerMemoryCleanup(window);
}
}
triggerMemoryCleanup(window) {
// 强制垃圾回收(如果启用)
if (process.env.NODE_ENV === 'development') {
window.webContents.forcefullyCrashRenderer();
window.reload();
} else {
window.webContents.executeJavaScript('window.gc && window.gc();');
}
}
cleanupMemory() {
this.windows.forEach((window, id) => {
if (!window.isFocused() && !window.isDestroyed()) {
window.webContents.executeJavaScript('window.gc && window.gc();');
}
});
}
}BrowserWindow 作为 Electron 应用的核心组件,提供了强大的窗口管理能力和丰富的自定义选项。通过合理配置窗口属性、优化资源使用、实现多窗口协同,开发者可以创建出既美观又高效的桌面应用程序。