从零到精通:Electron 窗口管理高级技巧

0 阅读5分钟

Electron BrowserWindow API 知识点总结

目录


1. BrowserWindow 基础使用

基本语法

// 在主进程中
const { BrowserWindow } = require('electron')

const win = new BrowserWindow({ width: 800, height: 600 })

// 加载远程 URL
win.loadURL('https://github.com')

// 或加载本地 HTML 文件
win.loadFile('index.html')

重要提示

  • BrowserWindow主进程模块
  • app 模块的 ready 事件触发之前,不能使用此模块
  • BrowserWindow 继承自 EventEmitter

2. 窗口配置选项

2.1 基础窗口选项

选项类型默认值说明
width/heightnumber-窗口宽高
x/ynumber-窗口位置
showbooleantrue是否显示窗口
transparentbooleantrue是否启用背景透明
titlestring-窗口标题
backgroundColorstring-窗口背景色

2.2 webPreferences 配置

webPreferences 是最重要的配置对象,用于设置网页功能:

const win = new BrowserWindow({
  width: 1200,
  height: 800,
  webPreferences: {
    nodeIntegration: false,        // 是否启用 Node.js 集成
    contextIsolation: true,        // 是否启用上下文隔离
    preload: path.join(__dirname, 'preload.js'),  // 预加载脚本路径
    sandbox: true,                 // 是否启用沙箱
    session: session,             // 指定会话
    partition: 'persist:name',    // 分区字符串
    zoomFactor: 1.0,              // 缩放系数
    webSecurity: true,            // 是否启用同源策略
  }
})
关键安全配置说明
配置项说明推荐值
nodeIntegration是否在页面中启用 Node.jsfalse
contextIsolation是否隔离预加载脚本与页面true
preload预加载脚本路径(可访问 Node API)必须设置
sandbox是否启用沙箱模式true
webSecurity是否启用同源策略true

2.3 字体相关配置

webPreferences: {
  defaultFontFamily: {
    standard: 'Times New Roman',
    serif: 'Times New Roman',
    sansSerif: 'Arial',
    monospace: 'Courier New',
    cursive: 'Script',
    fantasy: 'Impact'
  },
  defaultFontSize: 16,
  defaultMonospaceFontSize: 13,
  minimumFontSize: 0,
  defaultEncoding: 'ISO-8859-1'
}

3. 窗口自定义与展示

3.1 优雅地显示窗口

使用 ready-to-show 事件

避免闪烁的最佳实践:

const win = new BrowserWindow({ show: false })

win.once('ready-to-show', () => {
  win.show()
})
设置 backgroundColor 属性
const win = new BrowserWindow({ backgroundColor: '#2e2c29' })
win.loadURL('https://github.com')

// 支持的颜色格式
win.setBackgroundColor('hsl(230, 100%, 50%)')
win.setBackgroundColor('rgb(255, 145, 145)')
win.setBackgroundColor('#ff00a3')
win.setBackgroundColor('blueviolet')

3.2 窗口状态管理

// 最小化
win.minimize()

// 最大化
win.maximize()

// 取消最大化
win.unmaximize()

// 关闭窗口
win.close()

// 隐藏窗口
win.hide()

// 显示窗口
win.show()

// 设置窗口位置
win.setPosition(x, y)

// 设置窗口大小
win.setSize(width, height)

// 获取窗口边界
const bounds = win.getBounds()

4. 父子窗口与模态窗口

4.1 父子窗口

子窗口会始终显示在父窗口之上:

const { BrowserWindow } = require('electron')

const top = new BrowserWindow()
const child = new BrowserWindow({ parent: top })

child.show()
top.show()

4.2 模态窗口

模态窗口会禁用父窗口的交互:

const top = new BrowserWindow()
const child = new BrowserWindow({
  parent: top,
  modal: true,
  show: false
})

child.loadURL('https://github.com')
child.once('ready-to-show', () => {
  child.show()
})

4.3 父子窗口 vs 模态窗口区别

特性父子窗口模态窗口
父窗口交互可用禁用
显示层级始终在父窗口之上始终在父窗口之上
创建方式设置 parent同时设置 parentmodal

5. 页面可见性

页面可见性 API 的工作原理:

5.1 可见性状态规则

  1. 所有平台:可见性状态与窗口是否隐藏/最小化相关
  2. macOS 额外:窗口被其他窗口完全遮挡时,可见性为 hidden
  3. 初始状态:如果创建时使用 show: false,初始可见性为 visible
  4. 背景节流:禁用 backgroundThrottling 时,可见性状态保持为 visible

5.2 推荐实践

// 在可见性为 hidden 时暂停资源消耗操作
document.addEventListener('visibilitychange', () => {
  if (document.hidden) {
    // 暂停视频、动画、定时器等
  } else {
    // 恢复操作
  }
})

5.3 backgroundThrottling 配置

webPreferences: {
  backgroundThrottling: false  // 页面在后台时不禁用动画和计时器
}

6. 平台相关的注意事项

macOS

  • 模态窗口显示为附加到父窗口的工作表
  • 子窗口保持与父窗口的相对位置
  • 窗口遮挡状态会影响可见性

Windows 和 Linux

  • 子窗口不会随父窗口移动
  • 模态窗口类型在 Linux 上会变为 dialog
  • Linux 上许多桌面环境不支持隐藏模态窗口

Wayland (Linux)

  • 创建后无法通过程序调整窗口大小
  • 无法通过程序定位、移动、聚焦或模糊窗口
  • 如需这些功能,使用 --ozone-platform=x11 参数运行

7. 常用事件

7.1 窗口生命周期事件

// 页面标题更新
win.on('page-title-updated', (event, title, explicitSet) => {
  event.preventDefault()  // 阻止标题更改
})

// 窗口即将关闭(DOM beforeunload 之前触发)
win.on('close', (event) => {
  event.preventDefault()  // 阻止关闭
})

// 窗口已关闭
win.on('closed', () => {
  // 移除窗口引用
  win = null
})

7.2 事件触发顺序

1. close 事件(可阻止)
   ↓
2. DOM beforeunload 事件
   ↓
3. DOM unload 事件
   ↓
4. closed 事件(无法阻止)

7.3 其他常用事件

事件名说明
page-title-updated文档标题更改时
close窗口即将关闭时
closed窗口关闭后
focus窗口获得焦点
blur窗口失去焦点
maximize窗口最大化
unmaximize窗口取消最大化
minimize窗口最小化
restore窗口从最小化恢复
resize窗口大小改变
move窗口位置移动
ready-to-show渲染进程首次完成绘制

最佳实践总结

✅ 推荐做法

  1. 使用 ready-to-show 事件 显示窗口,避免闪烁
  2. 始终设置 backgroundColor,使应用更接近原生
  3. 保持 contextIsolation: true,增强安全性
  4. 使用预加载脚本 暴露必要的 API
  5. 设置 show: false 后再显示,提升用户体验
  6. 监听 closed 事件,正确清理窗口引用

❌ 避免做法

  1. 不要在不可信内容上启用 nodeIntegration
  2. 不要禁用 contextIsolation 除非必要
  3. 不要在渲染进程直接使用 Node.js API
  4. 不要忽略窗口关闭事件导致内存泄漏

附录:常用配置速查

// 安全配置模板
const win = new BrowserWindow({
  width: 1280,
  height: 720,
  minWidth: 800,
  minHeight: 600,
  show: false,
  backgroundColor: '#ffffff',
  webPreferences: {
    nodeIntegration: false,
    contextIsolation: true,
    sandbox: true,
    preload: path.join(__dirname, 'preload.js')
  }
})

win.once('ready-to-show', () => {
  win.show()
})

文档基于 Electron v28+ BrowserWindow API 编写