35

我已经window.addEventListener('DOMContentLoaded', function() {});用 jQuery替换了$(document).bind('ready', function() {});,因为第一个无法在 IE < 9 上工作,而且我不想玩.attachEvent()那个虚拟浏览器,如果我可以让 jQuery 本身很好地覆盖它的话。

更换后不久,我注意到DOMContentLoaded事件总是在页面加载/刷新后大约 0-2 毫秒触发(至少这是我的日志记录脚本记录的内容),而.ready()在页面刷新后总是需要至少 15-20 毫秒,以被解雇(再次 - 由脚本记录)。

我纯粹是为了满足我的好奇心,为什么会有如此“重大”的延迟?当然,对我来说没有问题,jQuery 稍后会触发该事件。只是,因为我想知道所有答案(并统治世界!:]),我睡不着!:]

编辑:在.ready() 函数文档中,一些用户(尼克(Nexxar))指出:“ jQuery 模拟 IE 上不存在的“DOMContentLoaded”事件,但使用的机制比其他浏览器上使用的事件触发得晚得多“ . 也许这是一样的,我问?

4

4 回答 4

24

假设浏览器支持该事件:

  1. 真实事件可以支持任何document。jQuery 只会使用document它被加载的内容,无论你传递给它什么。
  2. 即使事件已经发生,jQuery 也会异步触发事件。'DOMContentLoaded'如果事件已经发生,附加事件将不会执行任何操作。

这些浏览器没有延迟,请参阅http://jsfiddle.net/rqTAX/3/(记录的偏移量以毫秒为单位)。

对于不支持该事件的浏览器,jQuery 显然也适用于它们。它将使用与真实不同的hacky机制,并且DOMContentLoaded不一定会像真实一样立即触发DOMContentLoaded

// The DOM ready check for Internet Explorer
function doScrollCheck() {
    if ( jQuery.isReady ) {
        return;
    }

    try {
        // If IE is used, use the trick by Diego Perini
        // http://javascript.nwbox.com/IEContentLoaded/
        document.documentElement.doScroll("left");
    } catch(e) {
        setTimeout( doScrollCheck, 1 );
        return;
    }

    // and execute any waiting functions
    jQuery.ready();
}
于 2012-07-17T13:23:38.993 回答
5

jQuery 通过绑定到document'事件来模拟这个事件,这是在 oldIEreadystatechange中模拟的标准方式。DOMContentLoaded

根据 jQuery 来源,该事件“迟到”但在window.onload. 但是,我无法找到该事件何时准确触发。DOMContentLoaded当 DOM 构建完成并准备好编写脚本时readystatechange触发,因此在此之后触发;也许它等待布局渲染或类似的样式,或者在渲染/布局过程中稍后触发事件?

无论如何,它可能会在 之后 DOMContentLoaded触发,可能是由于 IE 决定将document'更新readyState为“完成”。

(如果有人有明确的答案,发表评论,我会更新这个答案;我很想知道它什么时候触发自己,我在任何文档或任何我期望的网站上都找不到这个答案怪癖模式。)

于 2012-07-17T13:46:43.033 回答
2

'ready' 似乎稍后会触发的另一个原因(在实践中)是可能有许多事件与它相关联。如果其中任何一个是长时间运行的同步操作,那么就绪事件将在很久以后出现。例如,我使用了 knockout.js,它可能需要 500 毫秒来初始化页面。


但是,使用您的最小测试页面当然不是这样。我尝试运行以下命令:

 console.log(window.performance.timing.domContentLoadedEventEnd -
             window.performance.timing.domContentLoadedEventStart);

即使对于您的简单超级页面,这也提供了大约 6 毫秒


我还拿了你的代码并通过 Chrome 的性能工具运行它,发现了一些有趣的事情:

在此处输入图像描述

  • 顺便说一句:垂直的蓝色条是DOMCONTENTLOADED,绿色是“第一次绘制”
  • 您可以看到,即使是对 DOMCONTENTLOADED 事件的超级简单函数调用也可能需要 5 毫秒(这是在 i7 上)。请记住,它需要被解析并且需要初始化。
  • 回调以青色(匿名)显示,第一个来自 DOMCONTENTLOADED 事件,第二个是“就绪”回调。
  • 您会注意到“Timer Fired”(即setTimeout)。所以它无论如何都不是瞬时的。

查看jQuery 源代码,您会发现它们实际上为回调设置了一个计时器:

// Handle it asynchronously to allow scripts the opportunity to delay ready
window.setTimeout( jQuery.ready );

我不完全确定他们在这里的意思(任何想法) - 但它解释了这种行为。我可以看到它有助于避免竞争条件,并阻止 UI 但我不清楚“延迟准备好”。

于 2017-02-22T00:36:10.710 回答
1

除了我,还有人使用 jQuery 吗?;)

jQuery 3.0开始,只$( handler )推荐使用语法
(相当于$( document ).ready( handler ))。

来自 API 文档:.ready()

于 2020-03-09T13:15:19.087 回答