![](/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.