Как я могу получить доступ к содержимому внутри <webview>(NW.JS / Electron)? - PullRequest
0 голосов
/ 12 января 2019

Я использовал тег <webview> в NW.JS для замены с использованием iFrames (из соображений производительности), но не смог найти подробностей ни по NWJS документам , ни по фактическим <webview> документы .

Я просто хотел получить document.title из <webview> и отправить его обратно в основной процесс.

1 Ответ

0 голосов
/ 12 января 2019

Ограниченная документация по Webview (доступная через NWJS / Electron) делает очень трудным понимание того, как делать основные вещи, такие как получение доступа к / изнутри Webview, так что, надеюсь, это поможет.

FYI - в контексте Electron и NWJS тег <webview> позволяет отображать веб-сайты (например, iframe), с тем преимуществом, что он выполняется в отдельном процессе. Это намного лучше для производительности, чем куча фреймов. <webview> содержит стандартный HTML-документ, сложность которого, скажем, в iframe заключается в том, что он выполняется в отдельном процессе.

Основным решением для связи между основным процессом и внутри <webview> является использование пользовательского метода ContentWindow.postMessage() Webview. Это в значительной степени основано на window.postMessage(). Используя postMessage() - в частности, отслеживание event.source - мы создаем коммуникационный мост между основным процессом и <webview>.

Как это работает (хотя бы один способ, который я нашел):

  1. Во-первых, свяжите EventListeners из основного процесса с <webview> и окном (чтобы позже прослушать сообщение, приходящее из <webview>)
  2. Когда элемент <webview> загружает URL, он вызывает contentload()
  3. contentload() вставит EventListener в <webview> и настроит элементы data / DOM, которые мы хотим получить из <webview>.
  4. Как только <webview> заканчивает загрузку, запускается loadstop()
  5. loadstop() отправит сообщение на <webview>, чтобы установить мост. Важно отметить, что здесь я использую webview.contentWindow.postMessage() вместо window.postMessage().
  6. <webview> отвечает данными, которые мы настроили на шаге 1
  7. Когда главный процесс получает ответ (через EventListener «message») от <webview>, он запускает receiveHandshake()
  8. Внутри receiveHandshake() теперь у вас есть доступ к данным, поступившим из <webview>. Это может быть заголовок страницы или что-то еще, что вы настроили в webviewInjectScript.
  9. Наконец, я звоню removeListeners(), чтобы удалить все настроенные нами EventListener, но вы можете продолжать отправлять сообщения туда и обратно.
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.

...