我正在尝试弄清楚如何在
main
进程和 BrowserView
之间交换消息。
我一直在“简单”
ipc
中的main
过程和renderer
过程之间使用react renderer page
。
但是现在,使用相同的技术,我在
console
的 BrowserView
中看不到收到的消息,据我所知,它的行为似乎与“正常”react renderer page
不同。
这篇SOF
帖子似乎证实了我的假设:Electron BrowserView Renderer process vs WebView
在
preload
中我定义:
declare global {
interface Window {
api: {
electronIpcSend: (channel: string, ...arg: any) => void;
electronIpcOn: (channel: string, listener: (event: any, ...arg: any) => void) => void;
}
}
}
在
main
我有:
function createWindowTypeC (url_string: string) {
WindowTypeC = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
nodeIntegrationInWorker: false,
sandbox: true,
nodeIntegrationInSubFrames: false,
webSecurity: true,
webviewTag: false,
preload: path.join(__dirname, "./preload/preload.js"), /* eng-disable PRELOAD_JS_CHECK */
}
})
// and load the index.html of the app.
// Emitted when the window is closed.
WindowTypeC.on('closed', () => {
WindowTypeC.removeBrowserView(view_C)
WindowTypeC = null
})
enforceInheritance(WindowTypeC.webContents)
// https://www.electronjs.org/docs/latest/api/browser-view
let view_C = new BrowserView()
view_C.webContents.once('did-finish-load', () => {
contents.focus()
view_C.webContents.send('ping', 'whoooooooooh!')
})
view_C.setAutoResize({
width: true,
height: true,
horizontal: true,
vertical: true
})
WindowTypeC.setBrowserView(view_C)
view_C.setBounds({ x: 0, y: 0, width: 800, height: 600 })
view_C.setBackgroundColor("#1e1e1e")
setTimeout(() => {
view_C.webContents.loadURL(url_string)
}, 200)
view_C.webContents.openDevTools({
mode: 'left'
})
}
在
App_C.tsx
时我有:
import * as React from 'react';
function App_C(props) {
window.api.electronIpcOn('ping', (event, message) => {
console.log("App_C-window.api.electronIpcOn-ping-message: ", message)
})
window.api.electronIpcSend('pong', "Hello from App_C.tsx")
return (
<div id="outer-container" className='outer-container'>
<h1>App_C</h1>
</div>
);
}
export default App_C;
执行代码,页面正确呈现,但我没有看到从
BrowserView
发送到 renderer
进程的任何消息。
第二个附带问题是:如何在返回的路上,在
BrowserView
进程发送的 renderer
中发送消息?
第三个问题:如何与
BrowserView
渲染的页面进行交互?
要从浏览器视图向主进程发送消息,您可以从浏览器视图使用console.log并在主进程中监视
console-message
:
view.webContents.on("console-message", (evt, logLevel, message, lineNumber, source) => {
if (source.endsWith("/mybrowserview.js"))
// do something with message
});
请注意,这将拾取所有控制台消息,因此您需要检查消息是否采用预期格式,如果不是则忽略它。例如,您的消息可以采用以下格式:
console.log('{"request":"myrequest","value":"myvalue"}');
然后您可以检查它是否是一个请求,例如:
view.webContents.on("console-message", (evt, logLevel, message, lineNumber, source) => {
if (source.endsWith("/mybrowserview.js"))
if (!isJsonString(message) || !message.includes('"request"'))
return;
// Looks like a valid request - do something with it
let jsn = JSON.parse(message);
if(jsn.request == "myrequest")
...
});
function isJsonString(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
要从 main 向 browserview 发送消息,您可以执行一些 javascript,例如调用 browserview 中已有的函数:
view.webContents.executeJavaScript('myfunction("some message")');
在浏览器视图中你会看到类似的内容:
function myfunction(message) {
// do something with message
if (message == "whatever")
...
}