Chrome 内容脚本不起作用:DOMContentLoaded 侦听器不执行 [英] Chrome content scripts aren't working: DOMContentLoaded listener does not execute

查看:71
本文介绍了Chrome 内容脚本不起作用:DOMContentLoaded 侦听器不执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写可纠正 1 个论坛上拼写错误的扩展程序.

I am trying to code extension that corrects misspellings on 1 forum.

我正在尝试使用内容脚本访问 <p> 标签,但它没有改变任何东西(使用下面的代码):

I am trying to access <p> tag, with content script, but it doesn't change anything (using the code below):

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

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

It doesn't change anything when added as an extension, apparently if I wget the page, and put the script there, all works. Any thoughts?

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

I know content scripts and WWW pages have different sandboxes, maybe content script can't access page (and tag)?

推荐答案

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

You are injecting your script after the event you are listening for fires (in this case, DOMContentLoaded). Thus, any code that you have in the listener will not be executed, because the event never fires after you have added your listener.

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

In Chrome extensions and Firefox WebExtensions, when specifying a time for a content script to be injected, you can specify "document_start", "document_end", or "document_idle".1 In a manifest.json this is the value stated for the run_at property. For tabs.executeScript(), it is the runAt property.

  • 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 事件触发之后.对run_at: document_idle 内容脚本何时运行?"的回答表明这是以下两者中的较早者:

  • document_start
    The injection takes place prior to the DOM being created, or scripts from the page being run. This means that document.body and document.head do not yet exist. The DOMContentLoaded and window load events have not yet fired. You can add things to the DOM by adding them to the document.documentElement. You may need to use a MutationObserver to watch for the elements you are interested in being added to the DOM, or wait for an event like DOMContentLoaded to indicate that the DOM is available.
  • document_end (default)
    The injection takes place after the DOM is complete, but before subresources (e.g. images and frames) are loaded. This is usually after DOMContentLoaded has fired, but before the window load event fires.
  • document_idle
    The injection takes place sometime after document_end and immediately after the window load event fires. The answer to "When does a run_at: document_idle content script run?" indicates that this is the earlier of:

  • window load 事件触发后,或者
  • DOMContentLoaded 事件触发后 200 毫秒.
  • After the window load event fires, or
  • 200ms after the DOMContentLoaded event fired.

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

This means that your content script will be injected after DOMContentLoaded has fired, but the window load event may, or may not, have already fired.

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

Any time you use a DOMContentLoaded listener, or a window load listener, you should always check the document.readyState prior to adding the listener to make sure that you are adding the listener prior to the DOMContentLoaded event being fired (or prior to the load event being fired, if that is what you are listening for). This should be normal habit when you want to listen for these events. If you add the listener after the event has fired, the listener will never be run.

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 侦听器,您可以使用以下内容:

For adding a window load listener, you could use something like:

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. 此答案的部分内容复制自 我对检测并处理活动 HTML 页面中的按钮点击"的回答.
  1. If you are using tabs.executeScript(), the value that you provide for runAt only indicates the earliest you want the script to be injected. If you are executing tabs.executeScript() prior to that time, then the injection is delayed until the specified time. Note that for document_start the point when executing tabs.executeScript() will be valid for a new page is a complex topic, which deserves its own question/answer.
  2. Portions of this answer were copied from my answer to "Detect and handle a button click in the active HTML page".

这篇关于Chrome 内容脚本不起作用:DOMContentLoaded 侦听器不执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆