Electron新窗口报错TypeError: 无法读取null的'on'属性
Electron 未捕获异常修复:TypeError: Cannot read properties of null (reading 'on')
问题现象
- 触发条件:仅在历史打开过DevTools(开发者检查器)的前提下打开新窗口时抛出异常,主窗口正常运行过程中不会复现
- 报错截图:

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

