1. DOMContentLoaded 在页面html、script、style加载完毕即可触发,无需等待所有资源(image/iframe)加载完毕。(IE9+)
2. onload是最早支持的事件,要求所有资源加载完毕触发。
3. onreadystatechange 开始在IE引入,后来其它浏览器也有一定的实现。涉及以下 document , applet, embed, frame, frameset, iframe, img, input:image, link, script, xml
标签的元素,都触发该事件。通常来讲,会有 loading /interactive/complete几个状态值。
对于页面加载完毕,检测的是 document.readystate === "complete" 状态。就目前IE6~8的测试结果来看,这个事件的触发约
等同于 onload 事件,
触发顺序上onload在后面。
其它需要注意的是:
1.
IE11+,对于script标签,onreadystatechange不再受支持,请用onload来判断js的加载完成。
(查看;https://msdn.microsoft.com/en-us/library/ms536957(v=vs.85).aspx)
2. 在IE中,document.readystate === "interactive" ,在图片、js加载完成之前就已经触发,所以不能用来模拟 DOMContentLoaded 事件。
// 模拟DOMContentLoaded ------- 不要这样用,这是错误的。
document.onreadystatechange = function () {
if (document.readyState == "interactive") {
initApplication();
}
}
(示例代码源自:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/readyState 。)
3. 如果你在onload的事件函数里面,再次监听 onload事件,那么,是不会再次触发函数的。
function addOnload(callback) {
if ( "undefined" != typeof(window.attachEvent) ) {
return window.attachEvent("onload", callback);
}
else if ( window.addEventListener ){
return window.addEventListener("load", callback, false);
}
}
function onload1() {
document.getElementById('results').innerHTML += "First onload executed.";
//没用的,onload2是不会被调用的.
addOnload(onload2);
}
function onload2() {
document.getElementById('results').innerHTML += "Second onload executed.";
}
addOnload(onload1);
(查看:http://www.stevesouders.com/blog/2014/09/12/onload-in-onload/)
因此,对于异步加载的JS,为了保证js能在onload里面触发,可以先判断
document.readystate === "complete",如果成功,则立即执行函数。
4. 最后,看看jQuery1.8里面,有关 ready 函数的实现:
// The ready event handler and self cleanup method
DOMContentLoaded = function() {
if ( document.addEventListener ) {
document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
jQuery.ready();
} else if ( document.readyState === "complete" ) {
// we're here because readyState === "complete" in oldIE
// which is good enough for us to call the dom ready!
document.detachEvent( "onreadystatechange", DOMContentLoaded );
jQuery.ready();
}
},
////////////////////////////////////////////////
jQuery.ready.promise = function( obj ) {
if ( !readyList ) {
readyList = jQuery.Deferred();
// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
if ( document.readyState === "complete" || ( document.readyState !== "loading" && document.addEventListener ) ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
setTimeout( jQuery.ready, 1 );
// Standards-based browsers support DOMContentLoaded
} else 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 {
// 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 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 );
}
// and execute any waiting functions
jQuery.ready();
}
})();
}
}
}
return readyList.promise( obj );
};
https://msdn.microsoft.com/en-us/library/ms536957(v=vs.85).aspx
https://github.com/dperini/ContentLoaded/blob/master/src/contentloaded.js
https://developer.mozilla.org/zh-CN/docs/Web/API/Document/readyState
http://www.stevesouders.com/blog/2014/09/12/onload-in-onload/