$(document).ready(function) 在DOM结构就绪时就触发了,但是传统的window.onload则是在DOM加载完毕且所有资源都下载完毕后才触发。
ready是浏览器兼容的,那么就分为两种情况
- 标准浏览器:标准浏览器非常简单,有 DOMContentLoaded 事件,当所有DOM解析完以后会触发这个事件
- 非标准浏览器
非标准浏览器麻烦一些,jquery用两个方式来保证
- 如果浏览器存在 document.onreadystatechange 事件,当该事件触发时,如果 document.readyState=complete 的时候,可视为 DOM 树已经载入
- doScroll检测:IE浏览器文档中说明,当页面 DOM 未加载完成时,调用 doScroll 方法时,会产生异常。那么我们反过来用,如果不异常,那么就是页面DOM加载完毕了,可以不断地通过能否执行 doScroll 判断 DOM 是否加载完毕
因此总流程就是:
同时,为了保证最后一定会调用ready方法,在上面每一种方式的最后都还是会为load事件绑定ready方法。
if ( document.readyState === "complete" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
//这里的setTimeout是为了异步
setTimeout( jQuery.ready, 1 );
// Standards-based browsers support DOMContentLoaded
//标准浏览器侦听事件接口:document.addEventListener
} else if ( document.addEventListener ) {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
// A fallback to window.onload, that will always work
//文章一开始说了,这里为了保证一定会触发ready,所以还针对onload也绑定一次回调
window.addEventListener( "load", jQuery.ready, false );
// If IE event model is used
} else {
//IE侦听事件接口:document.attachEvent
//如果有onreadystatechange事件,侦听之
// 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 );
// http://javascript.nwbox.com/IEContentLoaded/
// 见下边说明
// 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) {}
//如果是IE并且不是iframe
if ( top && top.doScroll ) {
(function doScrollCheck() {
if ( !jQuery.isReady ) {
try {
// Use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
//一直调用doScroll滚动,因为DOM渲染结束前,DOM节点是没有doScroll方法的,所以一直会异常
//直到DOM渲染结束了,这个时候doScroll方法不会抛出异常,然后就调用$.ready()
top.doScroll("left");
} catch(e) {
return setTimeout( doScrollCheck, 50 );
}
// and execute any waiting functions
jQuery.ready();
}
})();
}
}