![](/img/trans.png)
[英]Google Chrome Extension message passing with run_at document_start
[英]Chrome extension set to `run_at` `document_start` is running too fast?
编辑:我的Chrome浏览器出现问题并与我的脚本产生冲突,无论问题来源是什么,都可以完全重新安装。 如果我碰巧找出导致它的原因,我会把它包含在这里。
编辑2:只是为了让在2017年阅读此内容的人知道我没有忘记这一点,自从我之前的编辑以来我从未遇到过这个问题。
编辑3:这是2019年,到目前为止,我再也没遇到过这个问题。
我一直在学习如何创建一个简单的Chrome扩展程序,这是一个用户脚本端口。 该脚本与Tampermonkey完美配合,设置run at
到document-start
,所有需要document-start
捕获的必要事件都被捕获。
但是,当我在Chrome扩展程序中设置相同的设置时,我发现相同的运行设置比Tampermonkey更快,导致第一个函数失败:( Uncaught TypeError: Cannot call method 'appendChild' of null.
)因为它试图追加head
部分的脚本元素,直到0.010s后才存在。
到目前为止,我的脏解决方案是使用setInterval
函数,将计时器设置为10来检查document.head
存在,然后在条件为真时继续执行代码。
有没有什么方法可以让我正确地工作,而不必诉诸于setInterval
或者可能复制Tampermonkey的grant none
选项,它似乎在网页上下文中运行用户脚本?
以下是我的manifest.json文件:
{
"manifest_version": 2,
"content_scripts": [ {
"js": [ "simpleuserscript.user.js" ],
"matches": [ "https://www.google.com/*"],
"run_at": "document_start"
} ],
"converted_from_user_script": true,
"description": "Chrome extension",
"name": "Testing",
"version": "1"
}
如果Chrome会采用afterscriptexecute
事件,所有这一切都可以避免,但在此之前我会遇到load
事件。 我提前感谢你提供的任何帮助。
编辑:我已经尝试了回复中的建议:使用不同的run at
点,使用DOMContentLoaded
加到document.documentElement
。 所有都不成功,因为:1和2使脚本错过早期事件,3返回与尝试追加到document.head
时相同的TypeError。
当document.readyState = loading
时,必须插入/运行该脚本,否则它将错过早期必要事件,但不能太早到无法将子项附加到documentElement
或head
simpleuserscript.user.js
中的代码simpleuserscript.user.js
:
var script = document.createElement("script");
script.textContent = "console.log('success')";
if(document.head) {
document.head.appendChild(script);
} else if(document.documentElement) {
document.documentElement.appendChild(script);
}
控制台将显示TypeError: Cannot call method 'appendChild' of null
Chrome扩展内容的脚本 (从运行manifest.json
是在运行) document_start
, 做火之前document.readyState
文件已经达到interactive
-这是你要开始与大多数网页元素搞乱最早的。
但是,如果您愿意,可以立即注入大多数<script>
节点。 只是不要document.head
或document.body
因为它们还不存在。
追加到documentElement
。 例如:
var s = document.createElement ("script");
s.src = "http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js";
s.async = false;
document.documentElement.appendChild (s);
要么
var s = document.createElement ("script");
s.src = chrome.extension.getURL ("MyPwnCode.js");
s.async = false;
document.documentElement.appendChild (s);
如果要添加或修改其他 DOM元素,请在运行document_start
的脚本中等待DOMContentLoaded
事件,如下所示:
document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
function fireContentLoadedEvent () {
console.log ("DOMContentLoaded");
// PUT YOUR CODE HERE.
//document.body.textContent = "Changed this!";
}
您的问题是,当使用"run_at": "document_start"
,DOM中唯一被授予的元素是<html>
元素。 如果你想避免相对于页面加载的错误,比如试图访问一些尚未创建的元素,你将不得不:
使您的脚本在"document_idle"
或"document_end"
。 虽然"document_end"
仍然没有授予您页面的所有元素和资源都已完全加载(但DOM已经被解析),但"document_idle"
关键字将确保DOM已被解析并且在脚本运行之前已正确加载所有元素和资源。
或者,您可以继续使用"document_start"
将代码包装在"DOMContentLoaded"
侦听器中,这将使DOM在完全加载和解析时运行,类似于"document_idle"
。 这是一个例子:
document.addEventListener("DOMContentLoaded", function() { // Run your code here... });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.