Quasar+Electron中contextBridge方法仅主窗口可用,子窗口失效求助
Electron子窗口无法调用contextBridge暴露的API问题
我使用Quasar框架开发Electron应用,在electron-preload.ts中通过contextBridge暴露了myWindowAPI对象,包含ajouterFenetre、envoi等方法。主窗口中调用window.myWindowAPI?.ajouterFenetre()等方法可正常运行,但通过该API内的createWindow方法创建的子窗口无法调用myWindowAPI中的方法,请问原因是什么?
相关代码
electron-preload.ts
function createWindow() { let x, y; const currentWindow = BrowserWindow.getFocusedWindow(); if (currentWindow) { const [currentWindowX, currentWindowY] = currentWindow.getPosition(); x = currentWindowX + 24; y = currentWindowY + 24; } let newWindow: Electron.CrossProcessExports.BrowserWindow | undefined; newWindow = new BrowserWindow({ show: false, width: 1000, height: 600, x, y, frame: false, webPreferences: { //nodeIntegration: true, contextIsolation: true, } }); //newWindow.loadURL(`file://${__dirname}/app.html`); newWindow.loadURL(process.env.APP_URL); newWindow.webContents.openDevTools(); newWindow.webContents.on('did-finish-load', () => { if (!newWindow) { throw new Error('"newWindow" is not defined'); } if (process.env.START_MINIMIZED) { newWindow.minimize(); } else { newWindow.show(); newWindow.focus(); } }); newWindow.on('closed', () => { //windows.delete(newWindow); newWindow = undefined; }); /*newWindow.on('focus', () => { const menuBuilder = new MenuBuilder(newWindow); menuBuilder.buildMenu(); });*/ //windows.add(newWindow); return newWindow; } contextBridge.exposeInMainWorld('myWindowAPI', { ajouterFenetre () { createWindow() }, envoi (data: unknown) { //BrowserWindow.getFocusedWindow()?.webContents.send('ping', data) console.log('envoi', data) ipcRenderer.send('ping', data) }, on: () => { // Deliberately strip event as it includes `sender` ipcRenderer.on('ping2', (event, data) => { console.log('recoi 1', data) }) }, recoi: (func:(data: unknown) => void) => { //if (validChannels.includes(channel)) { // Deliberately strip event as it includes `sender` return ipcRenderer.on('ping2', (event, data) => { console.log('recoi 1', data) }) //ipcRenderer.on('ping', (event, data) => func(data)) //} }, /*recoi: () => new Promise((res) => { ipcRenderer.on('ping', (ev, data) => { console.log('recoi 1', data) res(data); }); }),*/ minimize () { console.log('minimize2') //BrowserWindow.getFocusedWindow()?.minimize() }, toggleMaximize () { const win = BrowserWindow.getFocusedWindow() if (win?.isMaximized()) { win.unmaximize() } else { win?.maximize() } }, close () { BrowserWindow.getFocusedWindow()?.close() } })
Vue组件调用代码
window.myWindowAPI?.ajouterFenetre()
问题原因
子窗口的BrowserWindow配置中未指定预加载脚本。主窗口能正常调用myWindowAPI是因为Quasar框架默认已经为主窗口配置了预加载脚本(即你的electron-preload.ts),但你手动创建子窗口时,只开启了contextIsolation: true,却没有设置preload属性指向预加载脚本文件。预加载脚本是渲染进程启动前运行的关键脚本,只有加载它,contextBridge才会将myWindowAPI暴露给当前窗口的全局对象。
解决方案
修改createWindow函数中BrowserWindow的webPreferences配置,添加preload属性,确保路径指向你的electron-preload.ts文件。注意要使用绝对路径,避免相对路径导致的加载失败问题,可借助Electron的app模块或path模块来拼接路径:
// 先引入需要的模块(在文件顶部) const { app, BrowserWindow } = require('electron'); const path = require('path'); // 修改createWindow中的webPreferences部分 webPreferences: { contextIsolation: true, // 配置预加载脚本路径,根据你的项目结构调整 preload: path.join(app.getAppPath(), 'src-electron/electron-preload.ts') }
注意:实际路径要根据你的Quasar项目中
electron-preload.ts的位置来调整,确保路径准确。
内容的提问来源于stack exchange,提问作者François Schuster
相关产品推荐
相关产品推荐

