【问题标题】:How to detect if DOMContentLoaded was fired如何检测 DOMContentLoaded 是否被触发
【发布时间】:2012-02-26 22:33:24
【问题描述】:

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

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

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

什么是正确的选择?

编辑:

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

【问题讨论】:

  • 设置一个设置属性或变量的监听器。如果已设置,则事件已被调度。当然,您可能使用的浏览器不支持该事件,在这种情况下它永远不会发生。
  • @RobG 对于 ado 不支持 DOMContentLoaded 的浏览器,我已经有了答案。对于那些,我使用 load 事件和 onload 事件。我仍然没有回答我提出的问题
  • 没有“onload”事件,有一个 onload 属性/属性用于设置 load 事件的侦听器。如果您想明确知道是否发生了 DOMContentLoaded,请设置一个侦听器并查看它是否被调用。

标签: javascript events readystate


【解决方案1】:

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

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

这个在 IE 和 webkit 中已经支持很久了。它在 3.6 中被添加到 Firefox。这是spec"loaded" 适用于旧版 Safari 浏览器。

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

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

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

This MDN documentation 也是一本很好的读物,有助于了解更多关于 DOM 状态的信息。

【讨论】:

  • 你没有回答这个问题。我想了解 DOMContentLoaded 事件,而不是加载事件。 load事件很简单,DOMContentLoaded我不知道。
  • @brunoais - 然后为 DOMContentLoaded 事件安装一个处理程序,并在它触发时设置一个标志。我认为没有其他选择。
  • 如果您想在文档已解析时包含,但子资源仍在加载,您也可以检查“交互式”。请参阅我添加到答案中的第二个示例。
  • 只是为这个讨论增添趣味ablogaboutcode.com/2011/06/14/…
  • 第一个代码 sn-p 不正确 - document.readyState == "interactive" 也可以表明 DOMContentLoaded 已被触发。见这里:developer.mozilla.org/en-US/docs/Web/API/Document/readyState
【解决方案2】:

您可以检查文档的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)不同,但它具有相同的实际目的,即它告诉您文档已完成加载并且已解析,但仍在加载图像、样式表和框架等子资源 (source)。

【讨论】:

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

如何在 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

您可以在页面加载过程中查看事件的完整顺序in this fiddle

【讨论】:

  • 在小提琴的 JS 开头添加 log(document.readyState); 有助于指出在交互之前发生的 document.readyState 的 loading 状态。我会将这一重要步骤添加到事件的顺序中。在这篇MDN readyState 文章中进行了概述。谢谢!
【解决方案4】:

试试这个或看看这个link

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

注意

如果您在&lt;link rel="stylesheet" ...&gt; 之后有一个&lt;script&gt;

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

【讨论】:

  • 不错的尝试,但这并不符合我真正追求的目标。这不检查事件是否已经被触发,只检查事件是否被触发。我知道如何检查事件是否被触发,但我不知道如何检查事件是否已经被触发
【解决方案5】:

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

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

然后检查:

if(loaded) ...

【讨论】:

  • 不错的尝试:)。不过,这并不是真正的答案。由于我希望它能够与所有(主要)浏览器以及异步和延迟一起正常工作,因此我不能确定它是否会因为 IE 而按预期工作。
  • IE 不是浏览器 :D
【解决方案6】:

事情是这样的,如果其他一些库(比如jQuery)已经使用了DOMContentLoaded,你就不能再使用它了。这可能是个坏消息,因为您最终无法使用它。你会说,为什么不直接使用$(document).ready(),因为,不!不是所有东西都需要使用jQuery,特别是如果它是一个不同的库。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-12
  • 2014-04-01
  • 1970-01-01
  • 2018-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多