我是 Electron 新手,不太擅长 React,所以如果这是超级基本的,请提前道歉。我正在创建一个小的 Electron 桌面应用程序,用户可以在其中输入一些关键字,选择一些选项等,然后会生成一个新窗口,并将根据他们选择的内容执行一些操作(例如,解析一些航班选项并将匹配的航班添加到购物车)。我通过执行以下操作成功获得了一个非常基本的版本:
Electron 加载主窗口,其中包含我的表单和选项
mainWindow = new BrowserWindow({ ... options here ... })
mainWindow.loadURL(startUrl);
我的 React 组件中有一个按钮,可以将信息发送到 IPC 通道:
....
<button id="sendSyncMsgBtn" onClick={handleClick}>Ping Main Process</button>
...
function handleClick(e) {
e.preventDefault();
console.log('The button was clicked.');
ipcRenderer.send(channels.SC_WINDOW, userData);
}
然后我的 Electron“主进程”接收此事件并生成新窗口并执行一些操作:
ipcMain.on(channels.SC_WINDOW, (event) => {
console.log('Received the event');
secondWindow = new BrowserWindow({... options here ...});
secondWindow.loadURL(flightBookerUrl);
secondWindow.webContents.on('did-finish-load', () => {
let code;
// log just to make sure it's working
code = `console.log('The code is executed')`;
secondWindow.webContents.executeJavaScript(code);
// click the "add item" button
code = `
var xPathRes = document.evaluate ('//*[@id="add-remove-buttons"]/input', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
xPathRes.singleNodeValue.click();
`;
secondWindow.webContents.executeJavaScript(code);
// click the "checkout now" button
code = `
var xPathRes = document.evaluate ('//*[@id="cart"]/a[2]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
xPathRes.singleNodeValue.click();
`;
secondWindow.webContents.executeJavaScript(code);
});
});
目前这似乎或多或少有效,但我一直在博客和教程上阅读“您永远不应该从主进程控制显示,您应该将所需的信息传递给渲染器进程并在那里执行操作”。我的问题是 - 鉴于我的“第二个窗口”正在打开一个我无法控制的外部 URL,我如何将其控制权交给渲染器进程?这可能吗?我会理解,如果我将第二个窗口重定向到另一个 React 组件,那么我可以使用该类的
render
组件来监听 IPC 通道。但是,当我打开一个我实际上并不负责的 URL 时,我该怎么做呢?或者,我应该在我自己的 React 组件上打开第二个窗口,该组件仅返回到外部 URL 的重定向,但也可以在其中包含一些附加功能?
或者,我是否应该忽略那些告诉我使用渲染器进程而不是主进程的帖子,因为他们正在谈论渲染您控制的页面?
在这个问题上我抓狂了——我认为它是如此基本,以至于我似乎无法通过谷歌搜索找到一个很好的解释(或者也许我只是在谷歌搜索错误的关键词),所以任何建议将不胜感激。
我会尽力澄清评论中给出的提示。 以下是文档中有关预加载脚本的说明:
BrowserWindow 的预加载脚本在可以访问 HTML DOM 以及 Node.js 和 Electron API 的有限子集的上下文中运行。
和
在渲染器中加载网页之前注入预加载脚本
这就是为什么您使用它来链接(公开您的 ipc 方法)页面中的主进程和渲染器进程。我所说的页面是指您使用
loadFile('path/to/your/page.html')
构建并加载的页面。
因此,要使用
loadURL('www.external.com')
操作在 BrowserView 中加载的外部页面的 dom :
首先在 BrowserView 的 webPreferences 中设置预加载脚本,这里
yourPreloadScript.js
const lbcView = new BrowserView({
webPreferences: {
partition: 'persist:mainSession',
devTools: true,
preload: join(__dirname, '../preload/yourPreloadScript.js')
}})
然后 在预加载脚本中,您可以直接访问 BrowserView Web 内容的窗口和 DOM,在您的情况下是要废弃的外部页面。
yourPreloadScript.js
window.addEventListener('load', ()=> {
// do whatever
document.querySelectorAll( ...etc.)
})
如果您愿意,可以使用预加载脚本来注入链接到渲染器脚本的脚本标记。
我想我已经看到人们使用 webContents.executeJavascript 方法来自主过程,但我认为它很混乱,我认为你不能通过这种方式干净地管理比非常小和简单的指令更多的内容。
回答迟了,但希望对新人有帮助😊
干杯