Chrome内容脚本无法正常工作:DOMContentLoaded侦听器无法执行

时间:2017-04-05 13:47:52

标签: javascript google-chrome google-chrome-extension content-script

我正在尝试编写用于纠正1个论坛拼写错误的扩展程序。

我正在尝试使用内容脚本访问<p>代码,但它不会改变任何内容(使用下面的代码):

document.addEventListener("DOMContentLoaded", function() {
    document.getElementsByTagName("P")[4].innerHTML = "correct_word"; 
}); 

当作为扩展名添加时,它不会改变任何内容,显然如果我wget页面,并将脚本放在那里,一切正常。有什么想法吗?

我的 manifest.json 文件:

{
    "manifest_version": 2,
    "name": "Extension",
    "description": "Description",
    "version": "1.0",
    "content_scripts": [{
        "run_at": "document_end",
        "matches": ["http://example.com/"],
        "js": ["script.js"]
    }],
    "web_accessible_resources": ["Filedeleted(really).html"]
}

我知道内容脚本和WWW页面有不同的沙箱,也许内容脚本无法访问页面(和标签)?

1 个答案:

答案 0 :(得分:14)

您正在侦听火灾事件后注入脚本(在本例中为DOMContentLoaded)。因此,您在侦听器中的任何代码都不会被执行,因为在添加侦听器后事件永远不会触发。

在Chrome扩展程序和Firefox WebExtensions中,指定注入content script的时间时,您可以指定"document_start""document_end""document_idle" 1 manifest.json 中,这是run_at属性的值。对于tabs.executeScript(),它是runAt属性。

  • document_start
    注入发生在创建DOM之前,或者来自正在运行的页面的脚本。这意味着document.bodydocument.head尚不存在。 DOMContentLoadedwindow load事件尚未解雇。您可以通过将它们添加到document.documentElement来向DOM添加内容。您可能需要使用MutationObserver来监视您有兴趣添加到DOM中的元素,或者等待DOMContentLoaded之类的事件来指示DOM可用。
  • document_end(默认)
    注入在DOM完成之后但在加载子资源(例如图像和帧)之前进行。这通常是在DOMContentLoaded被解雇后,但在window load事件触发之前。
  • document_idle
    注入发生在document_end之后的某个时间以及window load事件触发后。 answer to "When does a run_at: document_idle content script run?"表示这是较早的:

    • window load事件触发后,或
    • DOMContentLoaded事件发生后200毫秒。

    这意味着您的内容脚本将在DOMContentLoaded被触发后注入,但window load事件可能已经或可能未被触发。

在收听DOMContentLoadedwindow load时,您应先检查document.readyState

每当您使用DOMContentLoaded侦听器或window load侦听器时,您应始终在添加侦听器之前检查document.readyState以确保您是在被触发的DOMContentLoaded事件之前(或者在load事件被触发之前添加侦听器,如果这是您正在侦听的事件)。当你想听这些事件时,这应该是正常的习惯。如果在事件触发后添加侦听器,则永远不会运行侦听器。

要添加DOMContentLoaded侦听器,您应该使用类似:

的内容
if(document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded',afterDOMLoaded);
} else {
    afterDOMLoaded();
}

function afterDOMLoaded(){
    //Everything that needs to happen after the DOM has initially loaded.
}

要添加window load侦听器,您可以使用以下内容:

if(document.readyState !== 'complete') {
    window.addEventListener('load',afterWindowLoaded);
} else {
    afterWindowLoaded();
}

function afterWindowLoaded(){
    //Everything that needs to happen after the window is fully loaded.
}
  1. 如果您使用的是tabs.executeScript(),则您为runAt提供的值仅表示您希望脚本最早注入的值。如果您在此之前执行tabs.executeScript(),则注入将延迟到指定时间。请注意,对于document_start,执行tabs.executeScript()时对新页面有效的点是一个复杂的主题,值得自己提出问题/答案。
  2. 此答案的部分内容是从my answer to "Detect and handle a button click in the active HTML page"
  3. 复制而来的