You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Electron新窗口报错TypeError: 无法读取null的'on'属性

Electron 未捕获异常修复:TypeError: Cannot read properties of null (reading 'on')

问题现象

  • 触发条件:仅在历史打开过DevTools(开发者检查器)的前提下打开新窗口时抛出异常,主窗口正常运行过程中不会复现
  • 报错截图:
    报错界面截图

根因分析

原代码存在3个直接导致报错的问题:

  1. API误用:BrowserWindow.fromId() 的入参要求是BrowserWindow实例的自有id(即win.id属性),原代码错误传入了win.webContents.id(窗口内渲染进程webContents的id)。未开启DevTools时,窗口id与webContents id顺序分配碰巧匹配,不会触发问题;开启DevTools后,DevTools作为独立窗口会占用id序列,打乱原有的id对应关系,导致查询返回null值,调用null的on方法直接抛出类型错误。
  2. 未过滤内部窗口:browser-window-focus事件会对Electron创建的所有窗口触发,包括DevTools自身的工具窗口,这类窗口不承载业务逻辑,不应该绑定业务事件。
  3. 逻辑设计缺陷:每次窗口获得焦点就会重新注册maximize/unmaximize事件监听器,会造成监听器内存泄漏,事件触发时会重复执行多次回调。

修复方案

不需要在browser-window-focus事件里动态绑定窗口事件,直接在业务窗口创建完成后一次性绑定监听即可,参考实现:

// 窗口创建时(一般是new BrowserWindow()之后)直接绑定最大化/还原事件,不要放到focus回调里
function bindWindowMaximizeEvent(win) {
  // 过滤无效窗口、DevTools内部窗口
  if (!win || win.webContents.getURL().startsWith('chrome-devtools://')) return;
  // 只绑定一次,避免重复注册监听器
  if (win._maximizeEventBinded) return;
  win._maximizeEventBinded = true;

  win.on('maximize', () => {
    console.log("maximize detected", win.webContents.id);
    win.send('window-events', 'maximize');
  })
  win.on('unmaximize', () => {
    console.log("unmaximize detected", win.webContents.id);
    win.send('window-events', 'unmaximize');
  })
}

// 业务窗口创建完成后直接调用绑定方法即可
// 例:const newWin = new BrowserWindow({...})
// bindWindowMaximizeEvent(newWin)

如果需要全局监听所有新建的业务窗口,用browser-window-created事件替代focus事件,提前过滤DevTools窗口:

app.on('browser-window-created', (event, win) => {
  // 跳过DevTools内部窗口
  if (win.webContents.getURL().startsWith('chrome-devtools://')) return;
  win.once('ready-to-show', () => {
    bindWindowMaximizeEvent(win);
  })
})

注意:禁止使用browser-window-focus做事件绑定,否则每次窗口聚焦都会重复执行绑定逻辑,引发内存泄漏。

内容的提问来源于stack exchange,提问作者BBB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 05:30:56