javascript - Chrome 内容脚本不工作 : DOMContentLoaded listener does not execute

标签 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 页面有不同的沙箱,也许内容脚本无法访问页面(和标签)?

最佳答案

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

在 Chrome 扩展和 Firefox WebExtensions 中,当为 content script 指定时间时要被注入(inject),你可以指定"document_start""document_end",或者"document_idle"1manifest.json 这是为 run_at 属性声明的值。对于 tabs.executeScript() ,它是 runAt 属性。

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

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

    这意味着您的内容脚本将在 DOMContentLoaded 触发后被注入(inject),但是 window load 事件可能有也可能没有已经解雇了。

监听DOMContentLoaded时, 或 window load, 你应该检查 document.readyState第一

任何时候你使用一个DOMContentLoaded监听器,或者一个windowload监听器,你应该总是检查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 提供的值仅表示您希望脚本注入(inject)的最早时间。如果您在此时间之前执行 tabs.executeScript(),则注入(inject)会延迟到指定时间。请注意,对于 document_start,执行 tabs.executeScript() 时对新页面有效的时间点是一个复杂的主题,值得单独提问/回答。
  2. 此答案的部分内容复制自 my answer to "Detect and handle a button click in the active HTML page" .

关于javascript - Chrome 内容脚本不工作 : DOMContentLoaded listener does not execute,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43233115/

相关文章:

用于检测系统音量(声音)和插入的音频插孔的 Javascript

javascript - 在node.js中检索JSON数据时出错

javascript - map 标记未在屏幕截图中捕获

javascript - 选择元素不执行 onclick for chrome 中的选项

javascript - 如何查找 Chrome 中调用方法的位置?

javascript - Chrome 扩展 - 在全屏视频顶部显示自定义通知/弹出窗口(HTML 元素)

google-chrome-extension - 按 id 反向搜索 Chrome 扩展程序

javascript - HTML 元素从节点列表中消失

python - Selenium 无法打开指定的 URL 并显示数据 :,

javascript - Chrome 扩展程序 : Capture URL of the newest tab opened