window.onload和$(document).ready()的区别

1387

7
这里大部分答案都已经过时了。目前jQuery实现$().ready()的方式有时会在window.onload之后触发。 - Shikkediel
2
备注:$(window).on('load', function(){});是jQuery中window.onload的等效写法。 - JP Zhang
对于文档准备就绪函数,我们可以设置如下:document.addEventListener("DOMContentLoaded", function (event) {});而对于 window.onload,可以设置如下:window.addEventListener('load', function () {}); - user3497034
17个回答

1362

ready事件会在HTML文档加载完成后触发,而onload事件会在所有内容(例如图片)都加载完成后稍晚触发。

onload事件是DOM中的标准事件,而ready事件是jQuery特有的。 ready事件的目的是尽可能早地在文档加载后触发,以便向页面元素添加功能的代码不必等待所有内容加载完成。


1
@baptx 不同的结果,文档准备处理程序将在 DOM 有效准备后被触发,使用 Promise。DOMContentLoaded 不会。因此,当异步加载外部脚本时,设置文档 jQuery 准备处理程序确实非常有用。 - A. Wolff
1
FYI,@baptx提供的链接本身链接到一个基于DOMContentLoaded(当存在时)或readystatechanged(对于IE)的js函数:https://github.com/dperini/ContentLoaded/blob/master/src/contentloaded.js,因此大概就是实现jQuery的`ready`所需的内容。 - ToolmakerSteve
希望这篇文章对你有所帮助:http://tech-blog.maddyzone.com/javascript/document-ready-vs-window-load-vs-window-onload - Rituraj ratan
6
没有onload这样的事件。onload是一个存储函数的对象属性名称,当load事件被触发时将调用该函数。为使内容通俗易懂,有些微调。 - Scott Marcus
这个答案在实际的Chrome/Edge浏览器(2022-10)中是不正确的。如果您创建一个包含图像和两个事件的控制台日志的单页面,您将得到doc->window的顺序(如所述)。如果页面上没有任何内容(只有硬编码文本),则顺序将是window->doc。 - Alexander Mihailov
显示剩余6条评论

160

window.onload是内置的JavaScript事件,但由于其在不同浏览器(Firefox,Internet Explorer 6,Internet Explorer 8和Opera)中实现存在微妙的怪癖,因此jQuery提供了document.ready,它可以抽象出这些问题,并在页面的DOM准备就绪时立即触发(不等待图像等内容)。

$(document).ready(请注意,它不是未定义的document.ready)是一个jQuery函数,包装并提供以下事件的一致性:

  • DOMContentLoaded - 这是一个新的事件,在文档的DOM加载完成时触发(可能比图像等内容早一段时间); 在Internet Explorer和其他浏览器中略有不同
  • 以及window.onload(即使在旧浏览器中也实现),它会在整个页面加载完成后(图像,样式等)触发

21
这里存在一个小误解:无论在哪个浏览器中,windowload事件都实现得相当一致。jQuery和其他库试图解决的问题是您提到的那个,即直到所有依赖资源(如图像和样式表)加载完成之后,才会触发load事件,而这可能需要很长时间,直到DOM完全加载、渲染并准备好交互为止。在大多数浏览器中,当DOM准备好时触发的事件称为DOMContentLoaded,而不是DOMContentReady - Tim Down
2
@Tim Down:这里的关键词是“合理”,即使使用onload,至少以前还需要一些对象嗅探(在FF/IE/Opera方面存在差异)。至于DOMContentLoaded,你完全正确。编辑以澄清。 - Piskvor left the building
OK. Opera自古以来就有window.onload(自版本7开始?肯定是在版本9之前)。不确定您关于IE的观点是什么:您是否指的是当window.onload被分配并且<body>具有onload属性时会发生什么?这确实因浏览器而异,但应该避免这种情况。同意库确实简化了这种事情,但通常情况下,只要<body>元素中没有onload属性,window.onload = function() { ... };在所有主要浏览器中都能很好地工作。 - Tim Down
1
@Tim Down:我知道Opera曾经有这个功能,但它的事件触发器有点古怪(为了可靠地触发,可以使用document.onload)。至于window.onloadwindow.onload = fn1; window.onload = fn2; - 只有fn2会在onload时被调用。一些免费的Web主机会将自己的代码插入文档中,有时会覆盖页面内的代码。 - Piskvor left the building
2
写"document.ready"不正确吧?document对象没有ready方法,而是从$(document)调用返回的jQuery对象有。如果我说得对,请编辑此答案,因为这很令人困惑。 - A. Sallai
显示剩余2条评论

94

$(document).ready()是jQuery事件。当DOM准备就绪时(这意味着浏览器已解析HTML并构建了DOM树),JQuery的$(document).ready()方法会被调用。这使您可以在文档准备好进行操作时运行代码。

例如,如果浏览器支持DOMContentLoaded事件(许多非IE浏览器都支持此事件),则将在该事件上触发。(请注意,DOMContentLoaded事件仅在IE 9+中添加。)

有两种语法可供使用:

$( document ).ready(function() {
   console.log( "ready!" );
});

或者简写版本:

$(function() {
   console.log( "ready!" );
});

$(document).ready()的主要几点:

  • 它不会等待图片加载完成。
  • 用于在DOM完全加载时执行JavaScript。将事件处理程序放在这里。
  • 可以多次使用。
  • 如果收到"$未定义"的消息,请将$替换为jQuery
  • 如果要操作图像,则不使用此功能。请改用$(window).load()

window.onload()是一个原生的JavaScript函数。window.onload()事件在页面上所有内容加载完成后触发,包括DOM(文档对象模型)、横幅广告和图片。另一个区别是,虽然我们可以有多个$(document).ready()函数,但只能有一个onload函数。


4
小问题:IE的讨论措辞不够准确。IE(8及其以下版本)并非在文档的readyState达到complete之前“无法安全地触发”,而是IE缺少DOMContentLoaded事件。这不是一个“安全性”的问题,而是IE中缺失的一个功能,在IE 9中被添加进去了。 - ToolmakerSteve
你是正确的,所以我编辑了答案以反映你的评论并表示感谢! - James Drinkard
你说“它不会等待图像加载完毕。”那其他文件呢,尤其是js文件?在调用另一个文件中的函数之前,通常需要知道它是否已加载。 - Dariux
这是另一个完全不同的话题,但如果我理解你的问题,它基于你如何构造你的页面,包括你放置JS文件的顺序。这里有一个更详细的链接:http://ablogaboutcode.com/2011/06/14/how-javascript-loading-works-domcontentloaded-and-onload/ 希望对你有帮助,詹姆斯 - James Drinkard
为什么有人想要多次使用$(document).ready()? - Usman

51

小提示:

始终使用 window.addEventListener 将事件添加到窗口中。因为这样你可以在不同的事件处理程序中执行代码。

正确的代码:

window.addEventListener('load', function () {
  alert('Hello!')
})

window.addEventListener('load', function () {
  alert('Bye!')
})

无效代码:

window.onload = function () {
  alert('Hello!') // it will not work!!!
}

window.onload = function () {
  alert('Bye!') 
}

这是因为onload只是对象的属性,会被覆盖。类比于addEventListener,最好使用$(document).ready(),而不是onload。

13
这并没有回答所问的问题。 - user4639281

48

Windows加载事件会在页面上的所有内容,包括DOM(文档对象模型)内容、异步JavaScript框架和图像都完全加载完成后触发。您也可以使用body onload。两种方式是相同的;window.onload=function(){}<body onload="func();">是使用相同事件的不同方法。

jQuery $document.ready函数事件比window.onload早执行一点,并且在页面上的DOM(文档对象模型)加载完成后调用。它将不会等待图像和框架完全加载

取自以下文章: 如何区分$document.ready()window.onload()


1
我认为这是最好的答案! - Haoyu Chen
4
如果没有逐字复制的话,我可能会同意。 - Kevin B

27

$(document).ready(function() {

    // Executes when the HTML document is loaded and the DOM is ready
    alert("Document is ready");
});

// .load() method deprecated from jQuery 1.8 onward
$(window).on("load", function() {

     // Executes when complete page is fully loaded, including
     // all frames, objects and images
     alert("Window is loaded");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>


27

$(document).ready()是一个jQuery事件,在HTML文档被完全加载后发生,而window.onload事件则在稍后发生,当包括页面上的图像在内的所有内容都已加载。

此外,window.onload是DOM中的纯JavaScript事件,而$(document).ready()事件是jQuery中的方法。

$(document).ready()通常是jQuery包装器,以确保元素都已加载并可用于jQuery使用...

查看jQuery源代码以了解其工作原理:

jQuery.ready.promise = function( obj ) {
    if ( !readyList ) {

        readyList = jQuery.Deferred();

        // Catch cases where $(document).ready() is called after the browser event has already occurred.
        // we once tried to use readyState "interactive" here, but it caused issues like the one
        // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
        if ( document.readyState === "complete" ) {
            // Handle it asynchronously to allow scripts the opportunity to delay ready
            setTimeout( jQuery.ready );

        // Standards-based browsers support DOMContentLoaded
        } else if ( document.addEventListener ) {
            // Use the handy event callback
            document.addEventListener( "DOMContentLoaded", completed, false );

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

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

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

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

            try {
                top = window.frameElement == null && document.documentElement;
            } catch(e) {}

            if ( top && top.doScroll ) {
                (function doScrollCheck() {
                    if ( !jQuery.isReady ) {

                        try {
                            // Use the trick by Diego Perini
                            // http://javascript.nwbox.com/IEContentLoaded/
                            top.doScroll("left");
                        } catch(e) {
                            return setTimeout( doScrollCheck, 50 );
                        }

                        // detach all dom ready events
                        detach();

                        // and execute any waiting functions
                        jQuery.ready();
                    }
                })();
            }
        }
    }
    return readyList.promise( obj );
};
jQuery.fn.ready = function( fn ) {
    // Add the callback
    jQuery.ready.promise().done( fn );

    return this;
};

此外,我已经创建了下面的图片作为两者的快速参考:

在此输入图片描述


22

使用 $(document).ready() 时需注意与 Internet Explorer 的兼容性问题。如果在整个文档加载之前中断 HTTP 请求(例如,在页面正在流向浏览器时单击其他链接),IE 将触发 $(document).ready 事件。

如果 $(document).ready() 事件中的任何代码引用 DOM 对象,则这些对象有可能无法找到,从而导致 JavaScript 错误。要么保护对这些对象的引用,要么将引用这些对象的代码推迟到 window.load 事件中。

我未能在其他浏览器中(具体来说是 Chrome 和 Firefox)复现此问题。


哪个版本的IE?我知道应该关心兼容性,但是在IE上很难操作。仅针对JavaScript使用document.ready是否可行? - Monica
1
IE6、7和8。请参见:http://stackoverflow.com/questions/13185689/ie8-how-to-run-jquery-code-after-content-loads - James Drinkard

18

事件

$(document).on('ready', handler) 绑定了 jQuery 的 ready 事件。当DOM加载完毕时,会调用处理程序图片等资源可能仍然缺失。如果文档在绑定时已准备就绪,则永远不会被调用。jQuery使用DOMContentLoaded 事件来模拟它(如果不可用)。

$(document).on('load', handler) 是一种在所有资源从服务器上加载完成后触发的事件。现在图片已经加载完成了。虽然 onload 是一个原始的HTML事件,但 ready由jQuery构建。

函数

$(document).ready(handler) 实际上是一个Promise。如果文档在调用时已经准备好,处理程序将立即被调用。否则它会绑定到ready事件。

在 jQuery 1.8之前 $(document).load(handler) 存在作为 $(document).on('load',handler) 的别名。

进一步阅读

  • 已移除的事件别名

  • 你能否解释一下 $(document).load(handler) 和绑定到load事件的行为相同。与$.fn.ready不同,它不会立即调用。 - Nabeel Khan
    我想你可能被$.fn.load迷惑了,它不再像事件绑定器一样工作。事实上,自从jquery 1.8版本以后,它就已经过时了。我已经相应地进行了更新。 - abstraktor

    14

    window.onload: 一个普通的 JavaScript 事件。

    document.ready: 当整个 HTML 加载完毕时,它是 jQuery 中特定的事件。


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