【问题标题】:Chrome content scripts aren't working: DOMContentLoaded listener does not executeChrome 内容脚本不起作用:DOMContentLoaded 侦听器不执行
【发布时间】:2017-08-31 04:21:34
【问题描述】:

我正在尝试编写可纠正 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 页面有不同的沙箱,也许内容脚本无法访问页面(和标签)?

【问题讨论】:

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


    【解决方案1】:

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

    在 Chrome 扩展程序和 Firefox WebExtensions 中,当指定注入 content script 的时间时,您可以指定 "document_start""document_end""document_idle"11 em>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 事件可能已经触发,也可能未触发。

    在收听DOMContentLoadedwindowload时,应先检查document.readyState

    任何时候您使用DOMContentLoaded 侦听器或window load 侦听器时,都应该在添加侦听器之前检查document.readyState,以确保您在@987654368 之前添加侦听器@ 事件被触发(或者在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" 复制而来的。

    【讨论】:

    • oooooo myy godd 4 小时后...非常感谢。 StackOverflow 上的其他答案都没有解释 document.readyState
    • 太棒了!!谢谢。
    猜你喜欢
    • 2015-12-07
    • 2015-09-24
    • 2011-07-06
    • 2016-12-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2017-09-27
    • 1970-01-01
    相关资源
    最近更新 更多