JavaScript的load、ready、domready和DOMContentLoaded事件的区别

24

我在“创业”事件中有点迷茫——有很多不同的事件,在DOM和各种框架(如jQuery)中被命名不同。所有可能的启动事件是什么?它们有什么区别?你能展示一个简单的时间线来说明这些事件的触发顺序吗?

4个回答

11

.ready()

当一个页面被渲染后,JavaScript提供了load事件来执行代码,但是这个事件只有在所有资源(如图片)完全接收到后才会触发。在大多数情况下,只要DOM层次结构完全构建,脚本就可以运行。传递给.ready()的处理程序保证在DOM准备就绪后执行,因此这通常是附加所有其他事件处理程序和运行其他jQuery代码的最佳位置。使用依赖于CSS样式属性值的脚本时,重要的是在引用脚本之前引用外部样式表或嵌入样式元素。在需要已加载资产的情况下(例如,如果需要图像的尺寸),应该将代码放置在load事件的处理程序中。 .ready()方法通常与属性不兼容。如果必须使用load,请不要使用.ready(),或者使用jQuery的.load()方法将load事件处理程序附加到窗口或更具体的项目(如图像)。

参考:http://api.jquery.com/ready/

.load()

(待翻译)
这个方法是.on("load", handler)的快捷方式。当一个元素及其所有子元素都已经完全加载时,会向该元素发送load事件。可以将此事件发送到与URL相关联的任何元素:图像、脚本、框架、iframe和window对象。通常情况下,没有必要等待所有图像完全加载。如果代码可以更早地执行,通常最好将其放在发送到.ready()方法的处理程序中。
参考:http://api.jquery.com/load-event/

GlobalEventHandlers.onload


文档加载过程中会触发load事件。此时,文档中的所有对象都在DOM中,并且所有图像和子框架都已完成加载。还有Gecko特定的DOM事件,如DOMContentLoaded和DOMFrameContentLoaded(可以使用EventTarget.addEventListener()处理),它们在页面的DOM构建完成后被触发,但不等待其他资源完成加载。
跨浏览器回退:Internet Explorer 8支持readystatechange事件,可用于检测DOM是否准备就绪。在较早版本的Internet Explorer中,可以通过定期尝试执行document.documentElement.doScroll(“left”)来检测该状态,因为在DOM准备就绪之前,这段代码片段将抛出错误。像jQuery这样的通用JS库提供了跨浏览器方法来检测DOM是否准备就绪。还有一些独立脚本提供这个功能:contentloaded.js(仅支持一个监听器)和jquery.documentReady.js(尽管名字是这样的,但不依赖于jQuery)。参考:https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers.onload

代码:

document.addEventListener("DOMContentLoaded", function (event) {
    console.log("DOM fully loaded and parsed");
});

function load() {
    console.log("load event detected!");
}
window.onload = load;

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

$(window).load(function () {
    console.log('loaded');
});

时间轴演示:http://jsfiddle.net/HgJ33/


8

记录不同框架及其事件可能会很有趣:

这里是使用 jsFiddle 进行的测试系列。相同的 HTML,不同的框架,ms 的差异。

Mootools

window.onload = function () {
    var now = new Date().getTime() - time;
    console.log(now, 'onload')             // 14 ms
};
window.addEvent('load', function () {
    var now = new Date().getTime() - time;
    console.log(now, 'load')               // 15 ms
});
window.addEvent('domready', function () {
    var now = new Date().getTime() - time;
    console.log(now, 'domready')           // 1 ms
});

jQuery

window.onload = function () {
    var now = new Date().getTime() - time;
    console.log(now, 'onload')             // 20 ms
};
$(document).on('DOMContentLoaded', function () {
    var now = new Date().getTime() - time;
    console.log(now, 'DOMContentLoaded')   // 10 ms
});
$(document).on('ready', function () {
    var now = new Date().getTime() - time;
    console.log(now, 'ready')              // 20 ms
});

Dojo工具包

dojo.addOnLoad(function() {
    //do stuff
});

YUI

YUI().use('*',function(Y) {
    Y.on("domready", function() {
        //do stuff
    }, Y, "The DOMContentLoaded event fired.  The DOM is now safe to modify via script.");
});

原型对象
document.observe("dom:loaded", function() { 
    //do stuff
});

Sencha JS

Ext.onReady(function() {
    //do stuff
});

2
谢谢提供毫秒级别的信息,但我更想了解原则——事件是否基本上相同,以及它们与文档中实际事件发生的时间关系是何时 - Tomas

3
总的来说,之前的答案都非常好而且详尽。但是.ready()和DOMContentLoaded事件之间存在一个重要的区别。
大多数浏览器都提供类似的功能,即DOMContentLoaded事件,不过jQuery的.ready()方法有一个重要且实用的不同之处:如果DOM已准备好并且浏览器在代码调用.ready(handler)之前触发DOMContentLoaded,函数处理程序仍将被执行。相比之下,在事件触发后添加的DOMContentLoaded事件监听器永远不会被执行。
参考:https://api.jquery.com/ready/ 正如我们从中看到的一样,.ready()在所有情况下至少会执行一次。
例如,在浏览器控制台中,我们可以定义:
>> function sample()
{
  console.log('This is sample.');

  $( document ).ready(function ()
  {
    console.log("Ready is working in all cases.")
  });  
}
undefined

最终结果是:

>> sample();
undefined
This is sample. debugger eval code:3:11
Ready is working in all cases. debugger eval code:7:13
>> sample();
undefined
This is sample. debugger eval code:3:11
Ready is working in all cases. debugger eval code:7:13

我注意到在某些情况下,DOMContentLoaded事件从未被触发。我不得不切换到jQuery document.ready事件处理程序。请查看此链接https://javascript.info/onload-ondomcontentloaded#readystate。 - DhaneshM

2

更好的做法是从您想要的功能和需要支持的浏览器的角度来思考。

在操作文档对象模型(DOM)之前,您必须确保HTML页面已经通过网络加载并解析为树形结构。一种解决方法是将所有代码写在HTML文件的末尾,在解析HTML后才会处理这些javascript代码。另一种较新的标准方法是监听DOMReady或DOMContentLoaded事件或ready事件,以确保处理程序只在DOM准备就绪后运行。

在DOM树构建完成后,浏览器将请求图像、音频、视频等资源。当所有这些资源都加载完毕时,将触发窗口的load事件,此时页面已准备好完全渲染。

因此,您应该考虑您的代码是否可以在DOM树准备就绪时执行,或者您是否需要加载所有内容才能运行代码。如果本地JavaScript实现的DOM ready未覆盖您需要支持的所有浏览器,则可以使用jQuery DOMready,这也是其存在的原因。


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