如何检测 DOMContentLoaded 是否被触发

IT技术 javascript events readystate
2021-02-20 04:41:56

我正在尝试帮助开发一个库,为此我正在尝试处理页面加载。
在这个过程中我想让库完全兼容 defer 和 async 的使用。

我想要的很简单:
我怎么知道 DOMContentLoaded 在文件执行时被触发?

为什么这如此困难?
在 IE 中,document.readyState 在 DOMContentLoaded 之前显示交互。
不会以任何方式使用浏览器检测,这违反了我和其他参与者的政策。

什么是正确的选择?

编辑:

好像我说的不够清楚。没有兴趣知道是否已经发生加载事件!我已经知道如何解决这个问题了!我想知道如何用DOMContentLoaded解决!!!

6个回答

查看页面中的所有资源是否已加载:

if (document.readyState === "complete" || document.readyState === "loaded") {
     // document is already ready to go
}

这在 IE 和 webkit 中已经支持很长时间了。它是在 3.6 中添加到 Firefox 中的。这是规范"loaded"适用于较旧的 Safari 浏览器。

如果您想知道页面何时已加载和解析,但所有子资源尚未加载(更类似于DOMContentLoaded),您可以添加“交互式”值:

if (document.readyState === "complete" 
     || document.readyState === "loaded" 
     || document.readyState === "interactive") {
     // document has at least been parsed
}

除此之外,如果您真的只想知道 DOMContentLoaded 何时触发,那么您必须为此安装一个事件处理程序(在它触发之前)并在它触发时设置一个标志。

这个 MDN 文档也是关于了解更多关于 DOM 状态的很好的读物。

如果您想在文档被解析时包含,但子资源仍在加载,您也可以检查“交互式”。请参阅我添加到答案中的第二个示例。
2021-04-17 04:41:56
第一个代码片段不正确 -document.readyState == "interactive"也可能表明 DOMContentLoaded 被触发。请参阅此处:developer.mozilla.org/en-US/docs/Web/API/Document/readyState
2021-04-21 04:41:56
你不是在回答这个问题。我想了解 DOMContentLoaded 事件,而不是 load 事件。load 事件很简单,DOMContentLoaded 我不知道。
2021-05-01 04:41:56
2021-05-09 04:41:56
@brunoais - 然后为 DOMContentLoaded 事件安装一个处理程序,并在它触发时设置一个标志。我认为没有其他选择。
2021-05-15 04:41:56

您可以检查文档的readyState值,并通过这种方式判断事件是否被触发。这是在start()文档完成解析后运行命名函数的代码

if (/complete|interactive|loaded/.test(document.readyState)) {
    // In case the document has finished parsing, document's readyState will
    // be one of "complete", "interactive" or (non-standard) "loaded".
    start();
} else {
    // The document is not ready yet, so wait for the DOMContentLoaded event
    document.addEventListener('DOMContentLoaded', start, false);
}

请注意,上面的代码检测文档何时完成解析请注意,这与检测是否DOMContentLoaded被触发(在 之后 立即发生interactive)不同,但它具有相同的实际目的,即,它告诉您文档已完成加载并已被解析,但是子资源如图像、样式表和框架仍在加载()。

“一个更易读的正则表达式是 [...]” → 如果有选择,你应该总是更喜欢相同代码的更易读的版本。
2021-04-28 04:41:56
@DenilsonSáMaia 我同意。改变了它。
2021-04-28 04:41:56
你是对的,我被那里的评论误导了。我编辑了您的答案并修复了它并添加了更多信息;请让我知道你的想法。
2021-04-29 04:41:56
@LucioPaiva 谢谢,你是对的 - 但这仅意味着关于 DCL 的评论已经被解雇是不正确的。代码在所有情况下仍然可以完美运行,那么为什么是 -1?
2021-05-03 04:41:56
这是不正确的。DOMContentLoaded interactive(此处证明:jsfiddle.net/luciopaiva/grs82byv/20之后才被解雇
2021-05-05 04:41:56

如何在 DOMContentLoaded(或尽快)上正确运行某些东西

如果您需要等待 HTML 文档完全加载并解析以运行某些内容,那么您需要等待DOMContentLoaded,毫无疑问。但是,如果您无法控制脚本何时执行,则可能DOMContentLoaded在您有机会侦听事件时已被触发。

考虑到这一点,您的代码需要检查是否DOMContentLoaded已经被触发,如果是,则立即继续执行需要等待的任何内容DOMContentLoaded

function runWhenPageIsFullyParsed() {
    // your logic goes here
}

if (document.readyState === "complete") {
    // already fired, so run logic right away
    runWhenPageIsFullyParsed();
} else {
    // not fired yet, so let's listen for the event
    window.addEventListener("DOMContentLoaded", runWhenPageIsFullyParsed);
}

页面加载期间事件的正确顺序是:

  • document.readyState 更改为 interactive
  • windowDOMContentLoaded事件被解雇
  • document.readyState 更改为 complete
  • windowload事件被解雇load

您可以在此小提琴中检查页面加载期间事件的完整顺序

log(document.readyState);在您的小提琴中的 JS 开头添加有助于指出loadingdocument.readyState 在交互之前发生状态。我会将这一重要步骤添加到事件的顺序中。在此MDN readyState文章中进行了概述谢谢!
2021-05-03 04:41:56

试试这个或看看这个链接

<script>
    function addListener(obj, eventName, listener) { //function to add event
        if (obj.addEventListener) {
            obj.addEventListener(eventName, listener, false);
        } else {
            obj.attachEvent("on" + eventName, listener);
        }
    }

    addListener(document, "DOMContentLoaded", finishedDCL); //add event DOMContentLoaded

    function finishedDCL() {
        alert("Now DOMContentLoaded is complete!");
    }
</script>

笔记

如果你有<script>一个<link rel="stylesheet" ...>

页面不会完成解析 - 并且DOMContentLoaded不会触发 - 直到加载样式表

不错的尝试,但这并没有达到我真正追求的目标。这不检查事件是否已经被触发,只检查事件是否被触发。我知道如何检查事件是否被触发,但我不知道如何检查事件是否已经被触发
2021-05-13 04:41:56

如果你想“确切地”知道 DOMContentLoaded 是否被触发,你可以使用这样的布尔标志:

var loaded=false;
document.addEventListener('DOMContentLoaded',function(){
loaded=true;
...
}

然后检查:

if(loaded) ...
不错的尝试 :)。不过,这并不是真正的答案。由于我希望它能够在所有(主要)浏览器以及异步和延迟中正常工作,因此我不能确定由于 IE 的原因,它会按预期工作。
2021-04-30 04:41:56
IE 不是浏览器 :D
2021-05-08 04:41:56