窗口预加载脚本中的方法暴露给子窗口"/>
如何将主窗口预加载脚本中的方法暴露给子窗口
在我的 Game Launcher Electron 项目中,我试图通过单击按钮打开一个子窗口,并在其中提供其他功能。这些功能包括例如:打开 exe 文件。
为此我需要 Node.js,所以我尝试在预加载脚本中为此创建方法并通过 contextBridge 公开它们。
这些方法在主浏览器窗口中运行良好。但是,它们无法从子窗口访问(Uncaught ReferenceError: game is not defined)。请看下面的代码:
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,但这也不起作用(未定义要求)。
回答如下:这是因为您正在从渲染过程中打开“子窗口”。 IE:来自你的
renderer.js
文件。
这样做不会自动让您访问以前的窗口
preload.js
脚本。实际上,恰恰相反。
要从您的“子窗口”访问
preload.js
脚本,该窗口必须由 Electron 从主进程打开,就像您的主窗口一样。
实现此目的的最佳方法是,单击按钮后,从渲染进程主窗口向主进程发送 IPC 消息。当您的主进程收到消息时,它将使用相同的
preload.js
脚本打开您的“子窗口”,从而使您可以访问与主窗口相同的功能。
下面是一个最小的可重现示例。在开发者工具 - 两个窗口的控制台选项卡中检查
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>
更多推荐
如何将主窗口预加载脚本中的方法暴露给子窗口
发布评论