簡體   English   中英

設置為`run_at``document_start`的Chrome擴展程序運行得太快了?

[英]Chrome extension set to `run_at` `document_start` is running too fast?

編輯:我的Chrome瀏覽器出現問題並與我的腳本產生沖突,無論問題來源是什么,都可以完全重新安裝。 如果我碰巧找出導致它的原因,我會把它包含在這里。

編輯2:只是為了讓在2017年閱讀此內容的人知道我沒有忘記這一點,自從我之前的編輯以來我從未遇到過這個問題。

編輯3:這是2019年,到目前為止,我再也沒遇到過這個問題。


我一直在學習如何創建一個簡單的Chrome擴展程序,這是一個用戶腳本端口。 該腳本與Tampermonkey完美配合,設置run atdocument-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時,必須插入/運行該腳本,否則它將錯過早期必要事件,但不能太早到無法將子項附加到documentElementhead

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.headdocument.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM