gpt4 book ai didi

webview - 如何访问 (Electron/NW.JS) 的内容?

转载 作者:行者123 更新时间:2023-12-01 14:32:45 25 4
gpt4 key购买 nike

我使用的是 <webview>标记而不是 iFrame,但在 NWJS docs 上找不到更多详细信息, Electron docs , 也不是实际的 <webview> docs围绕访问其中的内容。

我想检索 document.title来自 <webview> ,并将其发送回主进程。

最佳答案

我使用的基本解决方案是在主进程和 <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);
}

它是如何工作的(至少是我发现的一种方式):

  1. 首先,将 EventListeners 从主进程绑定(bind)到 <webview>和窗口(稍后收听来自 <webview> 的消息)
  2. <webview>元素加载一个 URL,它触发 contentload()
  3. contentload()将向 <webview> 中注入(inject)一个 EventListener并设置我们想要从 <webview> 内部获取的数据/DOM 元素.
  4. 一旦<webview>完成加载,它触发 loadstop()
  5. loadstop()将向 <webview> 发送消息建立一座桥梁。重要的是要注意,这里我使用 webview.contentWindow.postMessage()而不是 window.postMessage() .
  6. <webview>响应我们在第 1 步设置的数据
  7. 当主进程收到来自 <webview> 的响应(通过 EventListener“消息”) , 它会触发 receiveHandshake()
  8. receiveHandshake() 内部您现在可以访问来自 <webview> 内部的数据.这可以是页面标题——或者您在 webviewInjectScript 中配置的任何内容.
  9. 最后,我调用 removeListeners()删除我们设置的所有 EventListener,但您可以继续来回发送消息。

仅供引用——在 Electron 和 NWJS 的上下文中,<webview>标记允许您呈现网站(如 iframe),其好处是它在单独的进程中运行。这比一堆 iframe 的性能要好得多。 <webview>包含一个标准的 HTML 文档,比 iframe 更复杂的是因为它在一个单独的进程中运行。

还有 another thread与其他一些解决方案一起使用,例如使用 IPC 消息和使用 preload标签。


更新:使用前端框架(即 Vue)

还有另一种方法更适合 Electron。在下面的代码中,我使用了 Vue (2) 和 Webpack,但与上述实现的主要区别是:

  • 使用 Electron ipcRendereripcMain发送消息,而不是 postMessage
  • 使用 preload 加载注入(inject)脚本Webview 的属性,而不是使用 executeScript() .我绑定(bind)了 :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>

mixins/injectWebPageScript.js

const { ipcRenderer } = require("electron");

// Once the Webview's document has been loaded, notify the ipcRenderer
document.addEventListener("DOMContentLoaded", () => {
ipcRenderer.on("requestData", () => {
ipcRenderer.sendToHost("replyData", {
title: document.title,
url: window.location.href
});
});
});

关于webview - 如何访问 <webview> (Electron/NW.JS) 的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54155507/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com