Chrome扩展程序不等待DOM加载

时间:2017-12-07 06:08:26

标签: javascript google-chrome-extension

我正试图通过内容脚本访问YouTube上的任何元素。

的manifest.json

"content_scripts": [
    {
      "run_at": "document_end",
      "matches": ["*://www.youtube.com/watch?v=*"],
      "js": ["content/content.js"]
    }
  ]

但是,在记录元素时,我有时会得到null,有时会记录该元素。

content.js

document.addEventListener('DOMContentLoaded', afterDOMLoaded)

function afterDOMLoaded() {
    const element = document.getElementById('top')
    console.log(element)
}

使用setTimeout

时有效
setTimeout(function(){ 
    const element = document.getElementById('top')
    console.log(element)
}, 3000)

我读到here这是因为该元素后来被页面的javascript动态添加,解决这个问题的唯一方法是使用MutationObserver / mutation-summary。这对于访问元素来说似乎很麻烦。没有别的办法吗?

2 个答案:

答案 0 :(得分:1)

尝试DOMSubtreeModified,它在每次修改DOM时触发:

document.addEventListener("DOMSubtreeModified", function(event){
        if(document.getElementById("my_element")) {
                //element is added
        }
});

答案 1 :(得分:0)

通过异步加载,我们将在" document_idle"处运行解决方案。 在" document_idle"的情况下,浏览器选择在" document_end"之间注入脚本的时间。在window.onload事件触发后立即启动。

更新manifest.json

"content_scripts": [ { "run_at": "document_idle", "matches": [ "*://www.youtube.com/watch?v=*" ], "js": [ "content.js" ] } ]

在内容脚本中,获取文档就绪状态并使用异步方式。

HTMLDocument.prototype.ready = new Promise(function (resolve) {
if (document.readyState != "loading")
    return resolve();
else
    document.addEventListener("DOMContentLoaded", function () {
        return resolve();
    });
});

document.ready.then(function () {
    const element = document.getElementById('top')
    console.log(element)
});

希望这有帮助。