Nic*_*ick 2 webview electron nwjs
我使用的是<webview>标签而不是 iFrame,但在NWJS 文档、电子文档以及有关访问其中内容的实际<webview>文档中找不到太多详细信息。
我想取回document.title从内<webview>,并发送回主过程。
我在主进程和 a 内部之间进行通信的基本解决方案<webview>是使用 Webview 的ContentWindow.postMessage()方法。这与window.postMessage(). 通过使用postMessage()——特别是跟踪——event.source我们在主进程和<webview>.
const webview = document.getElementById('your-webview-element');
// <webview> Content is loaded
function contentload() {
// The following will be injected in the webview
const webviewInjectScript = `
var data = {
title: document.title,
url: window.location.href
};
function respond(event) {
event.source.postMessage(data, '*');
}
window.addEventListener("message", respond, false);
`;
webview.executeScript({
code: webviewInjectScript
});
}
// <webview> Loading has finished
function loadstop() {
webview.contentWindow.postMessage("Send me your data!", "*"); // Send a request to the webview
}
// Bind events
webview.addEventListener("contentload", contentload);
webview.addEventListener("loadstop", loadstop);
window.addEventListener("message", receiveHandshake, false); // Listen for response
function receiveHandshake(event) {
// Data is accessible as event.data.*
// This is the custom object that was injected during contentload()
// i.e. event.data.title, event.data.url
console.log(event.data)
// Unbind EventListeners
removeListeners();
}
// Remove all event listeners
function removeListeners() {
webview.removeEventListener("contentload", contentload);
webview.removeEventListener("loadstop", loadstop);
window.removeEventListener("message", receiveHandshake);
}
Run Code Online (Sandbox Code Playgroud)
它是如何工作的(至少我找到了一种方法):
<webview>和 窗口(稍后侦听来自 内部的消息<webview>)<webview>元素加载一个 URL 时,它会触发contentload() contentload()将一个 EventListener 注入到 中<webview>并设置我们想要从<webview>.<webview>完成加载,它就会触发loadstop()loadstop()将向 发送消息<webview>以建立桥接。需要注意的是,这里我使用webview.contentWindow.postMessage()代替window.postMessage().<webview>与步骤1中的数据,我们建立响应<webview>,它会触发receiveHandshake()receiveHandshake()你现在有机会从内部传来的数据<webview>。这可以是页面标题,也可以是您在webviewInjectScript.removeListeners()删除我们设置的所有 EventListeners,但您可以继续来回发送消息。仅供参考 - 在 Electron 和 NWJS 的上下文中,该<webview>标签允许您呈现网站(如 iframe),其好处是它在单独的进程中运行。这比一堆 iframe 的性能要好得多。A<webview>包含一个标准的 HTML 文档,复杂的说 iframe 是因为它在一个单独的进程中运行。
还有其他一些解决方案的线程,例如使用 IPC 消息和使用preload标签。
还有另一种更适合 Electron 的方法。在下面的代码中,我使用了 Vue (2) 和 Webpack,但与上述实现的主要区别是:
ipcRenderer和ipcMain发送消息,而不是postMessagepreloadWebview的属性加载注入脚本,而不是使用executeScript(). 我已将该:preload值绑定到 Vue 计算属性 ( injectScript),它返回外部injectWebPageScript.js文件的路径。组件/myComponent.vue
<template>
<webview ref="frame" class="frame" :preload="injectScript"/>
</template>
<script>
export default {
computed: {
injectScript() {
const appPath = require("electron").remote.app.getAppPath();
return `file://${require("path").resolve(
__dirname,
"../../mixins/injectWebPageScript.js"
)}`;
}
},
methods: {
mySiteLoaderScript(url) {
const frame = this.$refs.frame;
// Initialize event listeners on the Webview
addListeners();
// Set the URL, start loading
frame.setAttribute("src", url);
// Bind events
function addListeners() {
frame.addEventListener("dom-ready", contentloaded);
frame.addEventListener("ipc-message", receiveHandshake);
}
// Remove all event listeners
function removeListeners() {
frame.removeEventListener("dom-ready", contentloaded);
frame.removeEventListener("ipc-message", receiveHandshake);
}
// Once webview content is loaded, request its data
function contentloaded() {
frame.send("requestData");
}
// Triggered when we receive a response from the Webview
// This is the `ipc-message` event
function receiveHandshake(event) {
// Only listen to replyData messages
if (event.channel !== "replyData") return false;
const data = event.args[0];
const title = data.title;
const favicon = data.favicon;
// Remove listeners once data has been received
removeListeners();
}
}
},
mounted() {
this.mySiteLoaderScript("https://stackoverflow.com");
}
};
</script>
Run Code Online (Sandbox Code Playgroud)
mixins/injectWebPageScript.js
<template>
<webview ref="frame" class="frame" :preload="injectScript"/>
</template>
<script>
export default {
computed: {
injectScript() {
const appPath = require("electron").remote.app.getAppPath();
return `file://${require("path").resolve(
__dirname,
"../../mixins/injectWebPageScript.js"
)}`;
}
},
methods: {
mySiteLoaderScript(url) {
const frame = this.$refs.frame;
// Initialize event listeners on the Webview
addListeners();
// Set the URL, start loading
frame.setAttribute("src", url);
// Bind events
function addListeners() {
frame.addEventListener("dom-ready", contentloaded);
frame.addEventListener("ipc-message", receiveHandshake);
}
// Remove all event listeners
function removeListeners() {
frame.removeEventListener("dom-ready", contentloaded);
frame.removeEventListener("ipc-message", receiveHandshake);
}
// Once webview content is loaded, request its data
function contentloaded() {
frame.send("requestData");
}
// Triggered when we receive a response from the Webview
// This is the `ipc-message` event
function receiveHandshake(event) {
// Only listen to replyData messages
if (event.channel !== "replyData") return false;
const data = event.args[0];
const title = data.title;
const favicon = data.favicon;
// Remove listeners once data has been received
removeListeners();
}
}
},
mounted() {
this.mySiteLoaderScript("https://stackoverflow.com");
}
};
</script>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2473 次 |
| 最近记录: |