javascript 如何在 Electron 中访问 <webview> 的 DOM?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33523171/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 16:35:18  来源:igfitidea点击:

How can I access the DOM of a <webview> in Electron?

javascriptjquerywebviewelectron

提问by NetOperator Wibby

I'm just getting started with Electron, with prior experience with node-webkit (nw.js).

我刚刚开始使用 Electron,之前有使用 node-webkit (nw.js) 的经验。

In nw.js, I was able to create iframes and then access the DOM of said iframe in order to grab things like the title, favicon, &c. When I picked up Electron a few days ago to port my nw.js app to it, I saw advice to use webviews instead of iframes, simply because they were better. Now, the functionality I mentioned above was relatively easy to do in nw.js, but I don't know how to do it in Electron (and examples are slim to none). Can anyone help?

在 nw.js 中,我能够创建 iframe,然后访问所述 iframe 的 DOM 以获取标题、网站图标等内容。几天前,当我拿起 Electron 将我的 nw.js 应用程序移植到它时,我看到了使用 webviews 而不是 iframes 的建议,仅仅是因为它们更好。现在,我上面提到的功能在 nw.js 中相对容易实现,但我不知道如何在 Electron 中实现(示例很少甚至没有)。任何人都可以帮忙吗?

Also, I have back/forward buttons for my webview (and I intend on having more than one). I saw in the documentation that I could call functions for doing so on a webview, but nothing I have tried worked either (and, I haven't found examples of them being used in the wild).

另外,我的 webview 有后退/前进按钮(我打算有多个)。我在文档中看到我可以在 webview 上调用函数来执行此操作,但我尝试过的任何方法都不起作用(而且,我还没有找到在野外使用它们的示例)。

采纳答案by Timothy C. Quinn

Besides guest to host IPC calls as NetOperatorWibby, it is also very useful to go from host to guest. The only way to do this at present is to use the <webview>.executeJavaScript(code, userGesture). This api is a bit crude but it works.

除了作为NetOperatorWibby 的来宾到主机 IPC 调用之外,从主机到来宾也非常有用。目前唯一的方法是使用<webview>.executeJavaScript(code, userGesture)。这个api有点粗糙,但它有效。

If you are working with a remote guest, like "extending" a third party web page, you can also utilize webview preload attribute which executes your custom script before any other scripts are run on the page. Just note that the preload api, for security reasons, will nuke any functions that are created in the root namespace of your custom JS file when your custom script finishes, however this custodial process will not nuke any objects you declare in the root. So if you want your custom functions to persist, bundle them into a singleton object and your custom APIs will persist after the page fully loads.

如果您正在使用远程访客,例如“扩展”第三方网页,您还可以利用 webview预加载属性,该属性在页面上运行任何其他脚本之前执行您的自定义脚本。请注意,出于安全原因,预加载 api 会在您的自定义脚本完成时取消在您的自定义 JS 文件的根命名空间中创建的任何函数,但是此保管过程不会取消您在根中声明的任何对象。因此,如果您希望自定义函数持续存在,请将它们捆绑到一个单例对象中,您的自定义 API 将在页面完全加载后持续存在。

[update] Here is a simple example that I just finished writing: Electron-Webview-Host-to-Guest-RPC-Sample

[更新] 这是我刚写完的一个简单例子:Electron-Webview-Host-to-Guest-RPC-Sample

回答by NetOperator Wibby

I dunno who voted to close my question, but I'm glad it didn't go through. Other people have this question elsewhere online too. I also explained what I wanted to achieve, but w/e.

我不知道谁投票结束我的问题,但我很高兴它没有通过。其他人在网上的其他地方也有这个问题。我还解释了我想要实现的目标,但是 w/e。



I ended up using ipc-message. The documentationcould use more examples/explanations for the layperson, but hey, I figured it out. My code is hereand here, but I will also post examples below should my code disappear for whatever reason.

我最终使用了ipc-message. 该文件可以使用更多的例子/解释为外行,但嘿,我想通了。我的代码在这里这里,但如果我的代码因任何原因消失,我也会在下面发布示例。



This code is in aries.js, and this file is included in the main renderer page, which is index.html.

此代码位于 中aries.js,并且此文件包含在主渲染器页面中,即index.html.

var ipc = require("ipc");
var webview = document.getElementsByClassName("tabs-pane active")[0];

webview.addEventListener("ipc-message", function (e) {
  if (e.channel === "window-data") {
    // console.log(e.args[0]);

    $(".tab.active .tab-favicon").attr("src", e.args[0].favicon);
    $(".tab.active .tab-title").html(e.args[0].title);
    $("#url-bar").val(e.args[0].url);

    $("#aries-titlebar h1").html("Aries | " + e.args[0].title);
  }

  // TODO
  // Make this better...cancel out setTimeout?
  var timer;

  if (e.channel === "mouseover-href") {
    // console.log(e.args[0]);
    $(".linker").html(e.args[0]).stop().addClass("active");

    clearTimeout(timer);

    timer = setTimeout(function () {
      $(".linker").stop().removeClass("active");
    }, 1500);
  }
});


This next bit of code is in browser.js, and this file gets injected into my <webview>.

这接下来的码位是browser.js,这个文件将被注入到我的<webview>

var ipc = require("ipc");

document.addEventListener("mouseover", function (e) {
  var hoveredEl = e.target;

  if (hoveredEl.tagName !== "A") {
    return;
  }

  ipc.sendToHost("mouseover-href", hoveredEl.href);
});

document.addEventListener("DOMContentLoaded", function () {
  var data = {
    "title": document.title,
    "url": window.location.href,
    // need to make my own version, can't rely on Google forever
    // maybe have this URL fetcher hosted on hikar.io?
    "favicon": "https://www.google.com/s2/favicons?domain=" + window.location.href
  };

  ipc.sendToHost("window-data", data);
});


I haven't found a reliable way to inject jQuery into <webview>s, and I probably shouldn't because the page I would be injecting might already have it (in case you're wondering why my main code is jQuery, but there's also regular JavaScript).

我还没有找到将 jQuery 注入<webview>s的可靠方法,我可能不应该这样做,因为我要注入的页面可能已经有了它(以防你想知道为什么我的主要代码是 jQuery,但也有常规的 JavaScript )。

回答by Sascha

This relates to previous answer (I am not allowed to comment): Important info regarding ipcmodule for users of Electron 1.x:

这与之前的答案有关(我不允许发表评论):有关ipcElectron 1.x 用户模块的重要信息:

The ipc module was split into two separate modules:

ipc 模块被分成两个独立的模块:

  • ipcMainfor the main process
  • ipcRendererfor the renderer process
  • 主进程的ipcMain
  • 用于渲染器进程的ipcRenderer

So, the above examples need to be corrected, instead of

所以,上面的例子需要更正,而不是

// Outdated - doesn't work in 1.x    
var ipc = require("ipc");

use:

利用:

// In main process.
var ipcMain = require('electron').ipcMain

And:

和:

// In renderer process.
var ipcRenderer = require('electron').ipcRenderer

See: http://electron.atom.io/blog/2015/11/17/electron-api-changessection on 'Splitting the ipc module'

请参阅:http: //electron.atom.io/blog/2015/11/17/electron-api-changes关于“拆分 ipc 模块”的部分