Как я могу получить доступ к содержимому <webview> (NW.JS/Electron)?
Я использовал <webview>
тег в NW.JS, чтобы заменить с помощью iFrames (по соображениям производительности), но не смог найти более подробную информацию ни о документах NWJS, ни о фактической <webview>
документы
Я просто хотел получить document.title
изнутри <webview>
и отправьте это обратно в основной процесс.
1 ответ
Ограниченная документация по Webview (доступная через NWJS/Electron) делает очень трудным понимание того, как делать основные вещи, такие как получение доступа к / изнутри Webview, так что, надеюсь, это поможет.
К вашему сведению - в контексте Электрон и NWJS, <webview>
Тег позволяет отображать веб-сайты (например, iframe), с тем преимуществом, что он запускается в отдельном процессе. Это намного лучше для производительности, чем куча фреймов. <webview>
содержит стандартный HTML-документ, сложность которого, скажем, в iframe заключается в том, что он выполняется в отдельном процессе.
Основное решение для связи между основным процессом и внутри <webview>
это использовать обычай Webview ContentWindow.postMessage()
метод. Это в значительной степени основано на window.postMessage()
, Используя postMessage()
- конкретно отслеживая event.source
- мы создаем коммуникационный мост между основным процессом и <webview>
,
Как это работает (по крайней мере, один способ, который я нашел):
- Во-первых, свяжите EventListeners из основного процесса с
<webview>
и окно (чтобы прослушать позже сообщение изнутри<webview>
) - Когда
<webview>
элемент загружает URL, он запускаетcontentload()
contentload()
вставит EventListener в<webview>
и настроить элементы данных /DOM, которые мы хотим получить изнутри<webview>
,- Однажды
<webview>
заканчивает загрузку, запускаетloadstop()
loadstop()
отправит сообщение<webview>
установить мост. Важно отметить, что здесь я используюwebview.contentWindow.postMessage()
вместоwindow.postMessage()
,-
<webview>
отвечает данными, которые мы настроили на шаге 1 - Когда основной процесс получает ответ обратно (через EventListener "message") от
<webview>
, это вызываетreceiveHandshake()
- Внутри
receiveHandshake()
Теперь у вас есть доступ к данным, которые пришли из<webview>
, Это может быть заголовок страницы или любой другой, который вы настроили вwebviewInjectScript
, - Наконец я звоню
removeListeners()
чтобы удалить все EventListeners, которые мы настроили, но вы можете продолжать отправлять сообщения туда и обратно.
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("loadstart", loadstart);
webview.removeEventListener("contentload", contentload);
webview.removeEventListener("loadstop", loadstop);
window.removeEventListener("message", receiveHandshake);
}
(Примечание: протестировано только в NW.JS). Информацию о поддержке Electron в Webview смотрите здесь. Есть также другая тема об использовании IPC в Electron. Это не вариант для меня с NW.JS.