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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 03:08:14