我正在尝试编写可纠正 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"
。1中manifest.json 这是为 run_at
属性声明的值。对于 tabs.executeScript()
,它是 runAt
属性。
document_start
注入(inject)发生在创建 DOM 或运行页面脚本之前。这意味着document.body
和document.head
还不存在。DOMContentLoaded
和window
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
监听器,或者一个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.
}
- 如果您正在使用
tabs.executeScript()
,您为runAt
提供的值仅表示您希望脚本注入(inject)的最早时间。如果您在此时间之前执行tabs.executeScript()
,则注入(inject)会延迟到指定时间。请注意,对于document_start
,执行tabs.executeScript()
时对新页面有效的时间点是一个复杂的主题,值得单独提问/回答。 - 此答案的部分内容复制自 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/