关于javascript:window.onload vs $(document).ready()

window.onload vs $(document).ready()

javascript的window.onload和jquery的$(document).ready()方法有什么区别?


ready事件发生在加载HTML文档之后,而onload事件则发生在加载所有内容(如图像)之后。

onload事件是DOM中的标准事件,而ready事件是jquery特有的。ready事件的目的是,它应该在文档加载后尽早发生,这样,为页面中的元素添加功能的代码就不必等待所有内容加载。


window.onload是内置的JavaScript事件,但是由于它的实现在浏览器(火狐、Internet Explorer 6、Internet Explorer 8和Opera)中有一些微妙的怪癖,jQuery提供了document.ready,它将这些抽象掉,并在页面的DOM准备就绪(不等待图像等)后立即激发。

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

  • document.ondomcontentready/document.ondomcontentloaded—在加载文档的dom(可能在加载图像等之前一段时间)时触发的一个新事件;同样,Internet Explorer和世界其他地方的情况略有不同。
  • window.onload(即使在旧浏览器中也实现了),当加载整个页面(图像、样式等)时会触发。


$(document).ready()是jquery事件。jquery的$(document).ready()方法在dom准备就绪后立即被调用(这意味着浏览器已经解析了HTML并构建了dom树)。这允许您在文档准备好被操作时立即运行代码。

例如,如果浏览器支持domcontentloaded事件(与许多非IE浏览器一样),那么它将触发该事件。(请注意,domcontentloaded事件仅添加到IE9+中的IE中。)

可以使用两种语法:

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

或速记版本:

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

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

  • 它不会等待加载图像。
  • 用于在DOM完全加载时执行javascript。在此处放置事件处理程序。
  • 可多次使用。
  • 当您收到"$未定义"时,用jQuery替换$
  • 如果要操作图像,则不使用。用$(window).load()代替。

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


当页面上的所有内容(包括DOM(文档对象模型)内容和异步JavaScript、框架和图像)都已完全加载时,将触发Windows加载事件。您还可以使用body onload=。两者都是相同的;window.onload = function(){}是使用同一事件的不同方式。

jquery $document.ready函数事件的执行时间比window.onload早一点,在页面上加载dom(文档对象模型)后调用。它不会等待图像、帧完全加载。

摘自以下文章:$document.ready()window.onload()的区别


关于在Internet Explorer中使用$(document).ready()的注意事项。如果在加载整个文档之前中断了HTTP请求(例如,当一个页面流到浏览器时,单击另一个链接),则IE将触发$(document).ready事件。

如果$(document).ready()事件中的任何代码引用了dom对象,则可能存在找不到这些对象的可能性,并且可能发生javascript错误。要么保护对这些对象的引用,要么延迟将这些对象引用到window.load事件的代码。

我无法在其他浏览器(特别是Chrome和Firefox)中重现这个问题。


1
2
3
4
5
6
7
8
9
10
11
12
13
$(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");
});
1
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js">


事件

$(document).on('ready', handler)绑定到jquery的ready事件。加载DOM时调用该处理程序。像图像这样的资产可能仍然丢失。如果文档在绑定时已就绪,则永远不会调用它。jquery为此使用domcontentloaded事件,如果不可用,则模拟它。

$(document).on('load', handler)是一个事件,当从服务器加载所有资源后,将触发该事件。现在加载图像。虽然onload是一个原始HTML事件,但ready是由jquery生成的。

功能

$(document).ready(handler)实际上是一种承诺。如果调用时文档已就绪,则将立即调用处理程序。否则,它将绑定到ready事件。

在jquery 1.8之前,$(document).load(handler)$(document).on('load',handler)的别名。

进一步阅读

  • 时机
  • 功能就绪
  • 一个例子
  • 承诺
  • 删除的事件别名


小贴士:

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

正确代码:

1
2
3
4
5
6
7
window.addEventListener('load', function () {
  alert('Hello!')
})

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

无效代码:

1
2
3
4
5
6
7
window.onload = function () {
  alert('Hello!') // it will not work!!!
}

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

这是因为onload只是对象的属性,它被覆盖。

addEventListener相比,最好使用$(document).ready()而不是onload。


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

window.onload也是DOM中的纯javascript事件,而$(document).ready()事件是jquery中的一个方法。

$(document).ready()通常是jquery的包装器,以确保所有加载的元素都用于jquery…

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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;
};

此外,我还创建了下面的图像作为这两个方面的快速参考:

enter image description here


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

document.ready:加载整个HTML时的特定jquery事件。


当所有元素都就位时,document.ready(jquery事件)将触发,并且可以在javascript代码中引用这些元素,但不必加载内容。加载HTML文档时执行document.ready

1
2
3
4
5
$(document).ready(function() {

    // Code to be executed
    alert("Document is ready");
});

但是,window.load将等待页面完全加载。这包括内部框架、图像等。

1
2
3
4
5
$(window).load(function() {

    //Fires when the page is loaded completely
    alert("window is loaded");
});


有一件事需要记住(或者我应该说回忆一下),那就是你不能像对待ready那样把onload堆叠起来。换句话说,jquery magic允许多个ready在同一个页面上,但不能用onload来实现。

最后一个onload将否决任何以前的onloads。

处理这个问题的一个好方法是使用一个Simon Willison编写的函数,并在使用多个javascript onload函数中进行了描述。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function addLoadEvent(func) {
    var oldonload = window.onload;
    if (typeof window.onload != 'function') {
        window.onload = func;
    }
    else {
        window.onload = function() {
            if (oldonload) {
                oldonload();
            }
            func();
        }
    }
}

// Example use:
addLoadEvent(nameOfSomeFunctionToRunOnPageLoad);
addLoadEvent(function() {
  /* More code to run on page load */
});

当HTML文档被加载时,document.ready事件发生;当所有内容(图像等)都被加载时,window.onload事件总是在稍后发生。

如果希望在渲染过程中"早期"进行干预,则可以使用document.ready事件,而无需等待图像加载。如果您需要在脚本"做某事"之前准备好图像(或任何其他"内容"),则需要等到window.onload

例如,如果要实现"幻灯片放映"模式,并且需要根据图像大小执行计算,则可能需要等到window.onload之后。否则,您可能会遇到一些随机问题,这取决于图像加载的速度。您的脚本将与加载图像的线程同时运行。如果您的脚本足够长,或者服务器足够快,如果图像恰好及时到达,您可能不会注意到问题。但最安全的做法是允许加载图像。

document.ready是一个很好的事件,您可以向用户显示一些"正在加载…"标志,在window.onload之后,您可以完成任何需要加载资源的脚本,然后最终删除"正在加载…"标志。

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// document ready events
$(document).ready(function(){
     alert("document is ready..");
})

// using JQuery
$(function(){
   alert("document is ready..");
})

// window on load event
function myFunction(){
  alert("window is loaded..");
}
window.onload = myFunction;

window.onload是一个javascript内置函数。加载HTML页面时,window.onload触发器。window.onload只能写入一次。

document.ready是jquery库的一个函数。当HTML和HTML文件中包含的所有JavaScript代码、CSS和图像完全加载时,document.ready触发。document.ready可根据需要多次写入。


当您说$(document).ready(f)时,您告诉脚本引擎执行以下操作:

  • 获取对象文档并将其推送,因为它不在本地范围内,所以必须执行哈希表查找以查找文档所在的位置,幸运的是,文档是全局绑定的,因此它是一个查找。
  • 找到对象$并选择它,因为它不在本地范围内,所以它必须执行哈希表查找,这可能有冲突,也可能没有冲突。
  • 在全局范围内查找对象f(这是另一个哈希表查找),或者推送函数对象并初始化它。
  • 调用所选对象的ready,这涉及到对所选对象的另一个哈希表查找,以查找并调用该方法。
  • 完成。
  • 在最好的情况下,这是2个哈希表查找,但这忽略了jquery所做的繁重工作,其中$是jquery所有可能输入的厨房接收器,因此可能存在另一个映射来将查询分派给正确的处理程序。

    或者,您可以这样做:

    1
    window.onload = function() {...}

    哪个将

  • 在全局范围内找到对象窗口,如果对javascript进行了优化,它会知道由于窗口没有更改,它已经选择了对象,所以不需要做任何事情。
  • 函数对象被推送到操作数堆栈上。
  • 通过执行哈希表查找来检查onload是否为属性,因为它是,所以像函数一样调用它。
  • 在最好的情况下,这需要一个哈希表查找,这是必要的,因为必须提取onload

    理想情况下,jquery会将其查询编译为字符串,这些字符串可以粘贴以执行您希望jquery执行的操作,但不需要运行时调度jquery。这样你就可以选择

  • 像今天一样动态地分派jquery。
  • 让jquery将您的查询编译为纯javascript字符串,该字符串可以传递给eval来执行您想要的操作。
  • 将2的结果直接复制到代码中,跳过eval的成本。