jQuery(document).ready会在多久之后被调用?

8
如果第三方JavaScript文件挂起并需要较长时间才能加载,那么...
jQuery(document).ready(function() {}) 

在被调用之前必须等待加载吗?

3个回答

13

需要等待,特别是你不能依赖于jQuery(document).ready()在其他脚本有机会执行之前触发。 ready绑定到DOMContentReady、readystatechanged或onload事件,取决于哪个可用。

文档说明"在大多数情况下,只要DOM层次结构完全构建就可以立即运行脚本"。请注意,唯一的保证是此事件触发时DOM已准备就绪。它不保证其它任何事情 - 因为它根本无法做到。

例如,这在IE、Firefox或Chromium中都不起作用,brilliant.js总是在ready()处理程序有机会执行之前调用,无论如何您设置脚本标记。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Test</title>
    <script src="http://ajax.microsoft.com/ajax/jQuery/jquery-1.4.2.js" charset="utf-8" type="text/javascript" ></script>
</head>
<body>
    <script type="text/javascript" >
    // <![CDATA[
        alert("attaching event");
        $(document).ready(function () { alert("fired"); });
    // ]]> 
    </script>
    <script type="text/javascript" src="brilliant.js" ></script>
</body>
</html>

提供参考,以下是 jQuery 1.4.2 的相关代码:

bindReady: function() {
    if ( readyBound ) {
        return;
    }

    readyBound = true;

    // Catch cases where $(document).ready() is called after the
    // browser event has already occurred.
    if ( document.readyState === "complete" ) {
        return jQuery.ready();
    }

    // Mozilla, Opera and webkit nightlies currently support this event
    if ( document.addEventListener ) {
        // Use the handy event callback
        document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

        // A fallback to window.onload, that will always work
        window.addEventListener( "load", jQuery.ready, false );

    // If IE event model is used
    } else if ( document.attachEvent ) {
        // ensure firing before onload,
        // maybe late but safe also for iframes
        document.attachEvent("onreadystatechange", DOMContentLoaded);

        // A fallback to window.onload, that will always work
        window.attachEvent( "onload", jQuery.ready );

        // If IE and not a frame
        // continually check to see if the document is ready
        var toplevel = false;

        try {
            toplevel = window.frameElement == null;
        } catch(e) {}

        if ( document.documentElement.doScroll && toplevel ) {
            doScrollCheck();
        }
    }
},

2

ready() 函数会在 John Resig 决定运行时运行。它可以在不同的浏览器上甚至是同一个浏览器的不同版本上的不同时间运行。你不能依赖它在其他脚本有机会执行之前触发你的事件处理程序。唯一确定的是当它被触发时,你能够访问 DOM。 - Andras Vass

2
第三方的js文件可能会阻塞加载,特别是如果它在head标签中。尝试将它放在<body>的结束标签之前。
我认为第一个答案是不正确的 - document.ready并不意味着所有内容都必须加载完成,它只是表示DOM已经完全加载。否则,在此内部运行的jquery方法将不会运行,直到所有图片(例如)都加载完成,这是不正确的。
编辑
看起来脚本的行为因浏览器而异,但可以是特定于浏览器的。这里有一个很好的解释:JavaScript:DOM加载事件、执行顺序和$(document).ready()。

1
根据 Mozilla 的 "DOMContentLoaded" 事件文档,"ready" 和 "load" 之间的关键区别在于页面在调用 "ready"(即 Firefox 或 Webkit 中的 "DOMContentLoaded" 处理程序)之前不会等待图像加载。并没有提到脚本文件是否完成。考虑到我们正在谈论单线程模型,我不明白在浏览器仍在解析/执行 <body> 结束之前遇到的 <script> 块时如何调用 "ready" 处理程序。 - Pointy
1
一个带有缓慢脚本的测试页面加载在body末尾,总是导致该脚本在jQuery“ready”处理程序被调用之前完成。 - Pointy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接