1. jQuery的3种针对文档加载的方法
$(document).ready(function() {
//你的代码
})
//document ready的简写
$(function() {
//你的代码
})
$(document).load(function() {
//你的代码
})
那么, jQuery 中的 ready 和 load 事件哪一个先执行? (这也是在面试中经常被问到的一个问题)
答案:ready 先执行,load 后执行。
解释
DOM文档的加载步骤:
- 解析HTML结构
- 加载外部脚本和样式表文件
- 解析并执行脚本代码
- 构造HTML DOM模型 // ready
- 加载图片等外部文件
- 页面加载完毕 // load
ready 是在第 4 步完成之后执行的,但是load是在第 6 步完成之后才执行。ready 和 load 的区别在于资源文件的加载, ready 构建了基本的 DOM 结构,对于用户来说,他们想第一时间就看到界面,而不是等到图片资源等都加载完之后才能看到界面,所以我们应该尽早处理 DOM,不需要等到图片资源都加载后才去处理,同时,大家也要知道,图片资源过多可能会导致 load 事件迟迟不能触发。
2. jQuery 是如何处理文档加载时机的
针对高级浏览器
jQuery.ready.promise = function( obj ) {
if ( !readyList ) {
readyList = jQuery.Deferred();
if ( document.readyState === "complete" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
setTimeout( jQuery.ready );
} else {
document.addEventListener( "DOMContentLoaded", completed, false );
window.addEventListener( "load", completed, false );
}
}
return readyList.promise( obj );
};
jQuery的ready是通过promise给包装过的,这也是jQuery擅长的手法,统一了回调体系。使用 DOMContentLoaded 事件,省时省力。
对于旧的 IE 如何处理呢?
// 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();
}
})();
}
如果浏览器存在 document.onreadystatechange 事件,当该事件触发时,如果 document.readyState=complete 的时候,可视为 DOM 树已经载入。不过,这个事件不太可靠,比如当页面中存在图片的时候,可能反而在 onload 事件之后才能触发,换言之,它只能正确地执行于页面不包含二进制资源或非常少或者被缓存时作为一个备选。
针对 IE 的加载检测
IE 在非 iframe 内时,只有不断地通过能否执行 doScroll 判断 DOM 是否加载完毕。在上述中间隔 50 毫秒尝试去执行 doScroll,注意,由于页面没有加载完成的时候,调用 doScroll 会导致异常,所以使用了 try -catch 来捕获异常。所以总的来说当页面 DOM 未加载完成时,调用 doScroll 方法时,会产生异常。那么我们反过来用,如果不异常,那么就是页面DOM加载完毕了 。
if ( document.readyState === "complete" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
setTimeout( jQuery.ready );
}
直接通过查看 readyState 的状态来确定页面的加载是否完成。