如何访问网页DOM而不是扩展页面DOM?

我正在编写一个Chrome扩展,并在popup.html文件中点击一个button后立即覆盖当前网页上的<div>

当我从popup.html中访问document.body.insertBefore方法时,它覆盖popup窗口上的<div> ,而不是当前网页。

我是否必须在background.html和popup.html之间使用消息才能访问网页的DOM? 我想在popup.html中做所有事情,如果可能的话也要使用jQuery。

正如在Chrome扩展概述中所述:体系结构 (这是一个必读):

如果您的扩展需要与网页交互,那么它需要一个内容脚本。 内容脚本是一些在已经加载到浏览器中的页面的上下文中执行的JavaScript。 将内容脚本视为所加载页面的一部分,而不是作为其打包的扩展的一部分(其父扩展名)。

一个popup式窗口( browserAction是Google Chrome浏览器工具栏中地址栏右侧的一个图标)也是HTML页面,使用chrome-extension:// URL,所以如果您访问其DOM,则会影响其页面。
这同样适用于背景/选项页面。

要访问/操作网页DOM,您有两种方法:

  1. manifest.json中声明内容脚本并使用消息传递 :

    chrome.tabs.sendMessage()从背景/popup页面到注入内容脚本的chrome.runtime.onMessage监听器,它将根据文档执行网页上的操作并通过sendResponsecallback传输结果(注意:只有像JSON一样的对象数字,string,数组,简单对象的支持,这意味着不是DOM元素,不是类,而不是函数)。 如果内容脚本需要启动与扩展页面的通信,则应使用chrome.runtime.sendMessage()

  2. 或者使用Tabs API来注入内容脚本
    chrome.tabs.executeScript(tabId, details, callback)

    • 所需的权限 : "tabs""https://www.example.com/*"
      (或"<all_urls>""\*://\*/\*""http://\*/\*""https://\*/\*"

    • 在明确的用户激活的情况下,更好的select是使用"activeTab"权限而不是"tabs""<all_urls>"因为它用作"<all_urls>"许多用途的替代scheme,但不显示警告消息安装期间

    • .executeScript()可以与一个callback函数一起使用,该函数在注入的内容脚本中接收最后一次计算的expression式的数组,每个帧中的一个元素int被注入到标签中。 Chrome在内部对结果使用JSON.parse()JSON.stringify() ,因此将支持的types限制为普通对象和简单的可串化值(如数字/string或其数组)。
      因此,它不适用于DOM元素,函数,自定义属性,getter / setter:您需要手动映射/提取所需的数据,并将其传递到一个简单的数组/对象中。

内容脚本在称为孤立世界的特殊环境中执行。 他们可以访问他们被注入的页面的DOM,但不能访问页面创build的任何JavaScriptvariables或函数。 它会查看每个内容脚本,就好像其上运行的页面上没有执行其他JavaScript一样。 反过来也是如此:在页面上运行的JavaScript不能调用任何函数或访问由内容脚本定义的任何variables。

仍然可以深入一些, 访问网页JavaScriptvariables/函数 。



作为第二种方法的一个例子,让我们在点击浏览器动作时显示div。
我们将在browserAction点击处理程序中使用chrome.tabs.executeScript()将内容脚本文件(或文字代码string(如果它很小,请参阅方法的文档)注入到该页面的DOM中。

 var someVar = {text: 'test', foo: 1, bar: false}; chrome.tabs.executeScript({ code: '(' + function(params) { document.body.insertAdjacentHTML('beforeend', '<div style="all:unset; position:fixed; left:0; top:0; right:0; bottom:0;' + 'background-color:rgba(0,255,0,0.3)">' + params.text + '</div>' ); return {success: true, html: document.body.innerHTML}; } + ')(' + JSON.stringify(someVar) + ');' }, function(results) { console.log(results[0]); }); 

正如您所看到的,我们已经使用了函数代码的自动string转换,以便能够将注入的代码作为正常的JavaScript语法突出显示和linting写入。 显而易见的缺点是浏览器浪费时间来parsing代码,但通常小于1毫秒,因此可以忽略不计。