electron 如何从主窗口的预加载脚本向子窗口公开方法

r3i60tvu  于 2023-05-15  发布在  Electron
关注(0)|答案(1)|浏览(138)

在我的游戏启动器电子项目我试图打开一个子窗口与按钮点击,并在那里,提供额外的功能。这些特征包括例如:打开exe文件。
为此,我需要Node.js,所以我尝试在preload脚本中创建方法,并通过contextBridge公开它们。
这些方法在主BrowserWindow中运行良好。但是,无法从子窗口访问它们(Uncaught ReferenceError:游戏未定义)。代码如下:
preload.js

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

contextBridge.exposeInMainWorld(
    'game', {
        open: () => {
            console.log('test');
        },
        openAddGamePage: () => {
            console.log('test');
        }
    }
);

renderer.js(主窗口的脚本),公开的方法在这里工作得很好。

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

addGame.js(来自addGamePage.html的脚本):这些方法在这里行不通

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

我还尝试在“addGame.js”中直接包含函数,并在创建子窗口时启用nodeIntegration,但这也不起作用(未定义require)。

ht4b089n

ht4b089n1#

这样做的原因是你正在从渲染过程中打开你的“子窗口”。IE:从您的renderer.js文件。
这样做不会自动给予您访问以前的windows preload.js脚本的权限。事实上,恰恰相反。
要从“子窗口”访问preload.js脚本,必须由Electron从主进程打开该窗口,就像主窗口一样。
实现此目的的最佳方法是,在单击按钮时,从渲染进程主窗口(主进程)发送IPC消息。当主进程收到消息时,它将使用相同的preload.js脚本打开“子窗口”,从而使您可以访问与主窗口相同的功能。
下面是一个最小可重复的示例。检查两个窗口的Developer Tools - Console选项卡中的test文本。
main.js(主工艺)

// Import required electron modules
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronIpcMain = require('electron').ipcMain;

// Import required Node modules
const nodePath = require('path');

// Prevent garbage collection
let launcherWindow;
let gameWindow;

function createLauncherWindow() {
    const launcherWindow = new electronBrowserWindow({
        x: 0,
        y: 0,
        width: 800,
        height: 600,
        show: false,
        webPreferences: {
            nodeIntegration: false,
            contextIsolation: true,
            sandbox: true,
            preload: nodePath.join(__dirname, 'preload.js')
        }
    });

    launcherWindow.loadFile(nodePath.join(__dirname, 'launcher-window.html'))
        .then(() => { launcherWindow.show(); });

    return launcherWindow;
}

function createGameWindow() {
    const gameWindow = new electronBrowserWindow({
        x: 150,
        y: 150,
        width: 800,
        height: 600,
        parent: launcherWindow,
        // modal: true, // Optional
        show: false,
        webPreferences: {
            nodeIntegration: false,
            contextIsolation: true,
            sandbox: true,
            // Let's use the same preload.js script
            preload: nodePath.join(__dirname, 'preload.js')
        }
    });

    gameWindow.loadFile(nodePath.join(__dirname, 'game-window.html'))
        .then(() => { gameWindow.show(); });

    return gameWindow;
}

electronApp.on('ready', () => {
    launcherWindow = createLauncherWindow();
});

electronApp.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        electronApp.quit();
    }
});

electronApp.on('activate', () => {
    if (electronBrowserWindow.getAllWindows().length === 0) {
        createLauncherWindow();
    }
});

// ---

electronIpcMain.on('open-game-window', () => {
    gameWindow = createGameWindow();
})

preload.js(主进程)

// Import the necessary Electron modules
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;

// Exposed protected methods in the render process
contextBridge.exposeInMainWorld(
    // Allowed 'game' methods
    'game', {
        openGameWindow: () => {
            ipcRenderer.send('open-game-window');
        },
        test: () => {
            console.log('test');
        }
    }
);

launcher-window.html(渲染过程)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Launcher Window</title>
        <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"/>
    </head>

    <body>
        <h1>Launcher Window</h1>
        <hr>
        <input type="button" id="openGameWindow" value="Open Game Window">
    </body>

    <script>
        // On button click, open the game window
        document.getElementById('openGameWindow').addEventListener('click', () => {
            window.game.openGameWindow();
        })

        // Testing
        window.game.test();
    </script>
</html>

game-window.html(渲染过程)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Game Window</title>
        <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"/>
    </head>

    <body>
        <h1>Game Window</h1>
    </body>

    <script>
        // Testing
        window.game.test();
    </script>
</html>

相关问题