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

Electron游戏启动器项目:如何将主窗口预加载脚本方法暴露给子窗口

问题解决:Electron子窗口无法访问预加载脚本暴露的API

核心原因

你通过window.open创建的子窗口没有加载预加载脚本,且新版本Electron中默认开启contextIsolation(上下文隔离),即使手动设置nodeIntegration=yes也无法直接使用require,必须通过预加载脚本的contextBridge注入API。

解决方案(推荐方式:主进程创建子窗口)

这种方式更符合Electron的安全规范,能明确控制窗口配置:

1. 修改主进程代码(如main.js)

const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');

// 创建主窗口
function createMainWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true, // 保持开启,符合安全规范
      nodeIntegration: false // 默认关闭,避免直接暴露Node.js API
    }
  });
  mainWindow.loadFile('index.html');
}

// 监听IPC请求,创建子窗口
ipcMain.handle('open-add-game-window', () => {
  const childWindow = new BrowserWindow({
    width: 600,
    height: 400,
    parent: BrowserWindow.getFocusedWindow(),
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'), // 子窗口必须加载预加载脚本
      contextIsolation: true,
      nodeIntegration: false
    }
  });
  childWindow.loadFile('features/addGame/addGamePage.html');
});

app.whenReady().then(createMainWindow);

2. 更新预加载脚本(preload.js)

新增IPC调用方法,让主窗口通知主进程创建子窗口:

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('game', {
  open: () => {
    console.log('test');
  },
  openAddGamePage: () => {
    ipcRenderer.invoke('open-add-game-window'); // 触发主进程创建子窗口
  }
});

3. 主窗口脚本(renderer.js)

document.getElementById('openAddGameWindow').addEventListener('click', () => {
  game.open();
  game.openAddGamePage(); // 调用预加载脚本暴露的方法,通知主进程创建子窗口
});

4. 子窗口脚本(addGame.js)

此时子窗口已加载预加载脚本,可直接访问game对象:

document.getElementById('addGameButton').addEventListener('click', () => {
  game.open();
});

备选方案:使用window.open并配置新窗口

如果坚持用window.open,需在主进程监听new-window事件,手动配置子窗口的预加载脚本:

1. 修改主进程代码(main.js)

const { app, BrowserWindow } = require('electron');
const path = require('path');

function createMainWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false,
      nativeWindowOpen: true // 启用原生window.open,才能监听new-window事件
    }
  });
  mainWindow.loadFile('index.html');

  // 拦截新窗口创建,手动配置参数
  mainWindow.webContents.on('new-window', (event, url) => {
    event.preventDefault();
    const childWindow = new BrowserWindow({
      parent: mainWindow,
      webPreferences: {
        preload: path.join(__dirname, 'preload.js'),
        contextIsolation: true,
        nodeIntegration: false
      }
    });
    childWindow.loadURL(url);
  });
}

app.whenReady().then(createMainWindow);

2. 主窗口脚本(renderer.js)

去掉nodeIntegration=yes参数:

document.getElementById('openAddGameWindow').addEventListener('click', () => {
  const childWindow = window.open('features/addGame/addGamePage.html', '_blank');
  game.open();
  game.openAddGamePage();
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 10:05:25