如何关闭Electron子窗口?调用childWin.close()无效的解决方案
Electron子窗口close()无效问题修复方案
问题根因
- 子窗口配置项
Parent大小写错误:Electron中BrowserWindow的父窗口绑定属性为小写parent,代码中写的大写Parent属于无效配置,父子窗口关系未正确绑定是childWin.close()不生效的核心原因 - 子窗口配置项
closeable拼写错误:正确属性名为closable,错误拼写会导致关闭相关配置不生效 - 未处理窗口销毁后的引用清理:全局变量
childWin在窗口关闭后仍持有旧引用,既会导致内存残留,也会影响后续窗口重建逻辑 - 未监听子窗口
closed事件:如果子窗口被用户手动关闭,全局变量仍持有已销毁的窗口对象引用,调用close()时会触发报错
修复后的完整代码
'use strict' import electron from 'electron' import { app, protocol, BrowserWindow } from 'electron' import { createProtocol } from 'vue-cli-plugin-electron-builder/lib' import installExtension, { VUEJS3_DEVTOOLS } from 'electron-devtools-installer' const isDevelopment = process.env.NODE_ENV !== 'production' // Scheme must be registered before the app is ready protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }]) let win const winWidth = 1000 const winHeight = 700 async function createWindow() { // Create the browser window. win = new BrowserWindow({ width: winWidth, height: winHeight, webPreferences: { // webSecurity false fixes CORS issues, remove in production! webSecurity: false, enableRemoteModule: true, nodeIntegration: true, contextIsolation: false } }) win.webContents.openDevTools({ mode: 'docked' }) win.setMenuBarVisibility(false) if (process.env.WEBPACK_DEV_SERVER_URL) { // Load the url of the dev server if in development mode await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL) if (!process.env.IS_TEST) win.webContents.openDevTools() } else { createProtocol('app') // Load the index.html when not in development win.loadURL('app://./index.html') } } let childWin = null const childWidth = 60 const childHeight = 60 async function createChildWindow() { // 避免重复创建子窗口 if (childWin) return // Create the browser window. childWin = new BrowserWindow({ width: childWidth, height: childHeight, frame: false, // 修复:拼写错误改为closable closable: true, webPreferences: { // webSecurity false fixes CORS issues, remove in production! webSecurity: false, enableRemoteModule: true, nodeIntegration: true, contextIsolation: false }, // 修复:将大写Parent改为小写parent,正确绑定父子窗口关系 parent: win }) const modalPath = process.env.NODE_ENV === 'development' ? `${process.env.WEBPACK_DEV_SERVER_URL}/#/electronMenu` : `file://${__dirname}/index.html#electronMenu` childWin.loadURL(modalPath) // 新增:监听子窗口关闭事件,清空引用 childWin.on('closed', () => { childWin = null }) } // Quit when all windows are closed. app.on('window-all-closed', () => { // On macOS it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q if (process.platform !== 'darwin') { app.quit() } }) app.on('activate', () => { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (BrowserWindow.getAllWindows().length === 0) createWindow() }) // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.on('ready', async() => { if (isDevelopment && !process.env.IS_TEST) { // Install Vue Devtools try { await installExtension(VUEJS3_DEVTOOLS) } catch (e) { console.error('Vue Devtools failed to install:', e.toString()) } } createWindow() createChildWindow() }) // Exit cleanly on request from parent process in development mode. if (isDevelopment) { if (process.platform === 'win32') { process.on('message', (data) => { if (data === 'graceful-exit') { app.quit() } }) } else { process.on('SIGTERM', () => { app.quit() }) } } electron.ipcMain.on('updateTileDataInElectronMenu', (event, tiles) => { // 新增:调用close前判断引用是否存在,避免报错 if (childWin) { childWin.close() // 需要重建子窗口时直接调用createChildWindow()即可 // createChildWindow() } })
子窗口重建逻辑
需要重建子窗口时,直接调用createChildWindow()即可,函数内部已经做了重复创建判断,会自动生成全新的子窗口实例。
内容的提问来源于stack exchange,提问作者Holiday
相关产品推荐
相关产品推荐

