如何访问网页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,您有两种方法:
-
在manifest.json中声明内容脚本并使用消息传递 :
chrome.tabs.sendMessage()
从背景/popup页面到注入内容脚本的chrome.runtime.onMessage
监听器,它将根据文档执行网页上的操作并通过sendResponse
callback传输结果(注意:只有像JSON一样的对象数字,string,数组,简单对象的支持,这意味着不是DOM元素,不是类,而不是函数)。 如果内容脚本需要启动与扩展页面的通信,则应使用chrome.runtime.sendMessage()
。 -
或者使用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毫秒,因此可以忽略不计。