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

Electron BrowserWindow API 知识点总结

目录

  • [1. BrowserWindow 基础使用](#1. BrowserWindow 基础使用 "#1-browserwindow-%E5%9F%BA%E7%A1%80%E4%BD%BF%E7%94%A8")
  • [2. 窗口配置选项](#2. 窗口配置选项 "#2-%E7%AA%97%E5%8F%A3%E9%85%8D%E7%BD%AE%E9%80%89%E9%A1%B9")
  • [3. 窗口自定义与展示](#3. 窗口自定义与展示 "#3-%E7%AA%97%E5%8F%A3%E8%87%AA%E5%AE%9A%E4%B9%89%E4%B8%8E%E5%B1%95%E7%A4%BA")
  • [4. 父子窗口与模态窗口](#4. 父子窗口与模态窗口 "#4-%E7%88%B6%E5%AD%90%E7%AA%97%E5%8F%A3%E4%B8%8E%E6%A8%A1%E6%80%81%E7%AA%97%E5%8F%A3")
  • [5. 页面可见性](#5. 页面可见性 "#5-%E9%A1%B5%E9%9D%A2%E5%8F%AF%E8%A7%81%E6%80%A7")
  • [6. 平台相关的注意事项](#6. 平台相关的注意事项 "#6-%E5%B9%B3%E5%8F%B0%E7%9B%B8%E5%85%B3%E7%9A%84%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9")
  • [7. 常用事件](#7. 常用事件 "#7-%E5%B8%B8%E7%94%A8%E4%BA%8B%E4%BB%B6")

1. BrowserWindow 基础使用

基本语法

javascript 复制代码
// 在主进程中
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/height number - 窗口宽高
x/y number - 窗口位置
show boolean true 是否显示窗口
transparent boolean true 是否启用背景透明
title string - 窗口标题
backgroundColor string - 窗口背景色

2.2 webPreferences 配置

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

javascript 复制代码
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.js false
contextIsolation 是否隔离预加载脚本与页面 true
preload 预加载脚本路径(可访问 Node API) 必须设置
sandbox 是否启用沙箱模式 true
webSecurity 是否启用同源策略 true

2.3 字体相关配置

javascript 复制代码
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 事件

避免闪烁的最佳实践:

javascript 复制代码
const win = new BrowserWindow({ show: false })

win.once('ready-to-show', () => {
  win.show()
})
设置 backgroundColor 属性
javascript 复制代码
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 窗口状态管理

javascript 复制代码
// 最小化
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 父子窗口

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

javascript 复制代码
const { BrowserWindow } = require('electron')

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

child.show()
top.show()

4.2 模态窗口

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

javascript 复制代码
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 推荐实践

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

5.3 backgroundThrottling 配置

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

6. 平台相关的注意事项

macOS

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

Windows 和 Linux

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

Wayland (Linux)

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

7. 常用事件

7.1 窗口生命周期事件

javascript 复制代码
// 页面标题更新
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 事件触发顺序

markdown 复制代码
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. 不要忽略窗口关闭事件导致内存泄漏

附录:常用配置速查

javascript 复制代码
// 安全配置模板
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 编写

相关推荐
前端那点事2 小时前
Vue3+TS动态路由终极方案|后端权限、刷新不丢、按钮权限、解决所有404BUG
前端·vue.js
前端那点事2 小时前
Vue3+TS手写不定高虚拟列表Hooks,彻底解决长列表卡顿,生产直接复用
前端·vue.js
ZC跨境爬虫2 小时前
跟着 MDN 学 HTML day_61:(构建反馈表单的结构化挑战)
前端·javascript·ui·html·音视频
卷帘依旧2 小时前
Vue2中defineProperty缺陷
前端
长安第一美人3 小时前
工业级实时监控系统开发:PHP+ZMQ+JS 前后端分离架构全解析
前端·嵌入式硬件·架构·交互·rk3588·zmq后端
ricardo19733 小时前
资源加载提速四件套:dns-prefetch / preconnect / preload / prefetch 实战
前端·面试
豹哥学前端3 小时前
JavaScript 异步编程完全指南:从回调地狱到 async/await,一次通关
前端·javascript·面试
kyriewen3 小时前
面试官让我手写Promise,我打开Cursor三秒生成,他愣了两秒说“你过了”
前端·javascript·面试
Bacon3 小时前
RAG 从入门到入土:Agent 时代,你的检索增强生成到底行不行?
前端·人工智能