jQuery中的ready函数

  • 为什么会有ready函数

在javascript中有window.onload函数,但是这个函数是在页面所有元素都加载完毕才执行的。而图片加载通常需要很长时间,这个ready函数就是可以让javascript函数在图片加载完毕前执行的方法。

通常我们需要操作HTML文档时必须要浏览器将文档模型对象加载完毕才能操作, $(document).ready(fn)d的含义就是 检测DOM对象模型是否加载完毕。

  • 通常如何判断

对于非IE浏览器通过监听事件DOMContentLoaded就可以了。

对于IE浏览器通常有两种方法

1. 检测onreadystatechange事件

2. 不断地检测documentElement.doScroll()方法是否可以安全执行

  • jQuery中如何实现

1. ready(fn) 提供给外界的绑定事件的借口。

源码展示:

Js代码

  1. ready: function( fn ) {
  2. jQuery.bindReady(); //添加监听函数
  3. if ( jQuery.isReady ) { //如果dom加载完成了
  4. fn.call( document, jQuery ); //立刻执行函数
  5. } else if ( readyList ) {
  6. readyList.push( fn ); //否则把函数添加进readyList
  7. }
  8. return this;
  9. },
ready: function( fn ) {
jQuery.bindReady(); //添加监听函数
if ( jQuery.isReady ) { //如果dom加载完成了
fn.call( document, jQuery ); //立刻执行函数
} else if ( readyList ) {
readyList.push( fn ); //否则把函数添加进readyList
}
return this;
},

2. jQuery.ready() 执行绑定的函数队列

jQuery.ready

Js代码

  1. ready: function() {
  2. if ( !jQuery.isReady ) {
  3.   if ( !document.body ) {
  4. return setTimeout( jQuery.ready, 13 );
  5. }
  6. jQuery.isReady = true; //设置isReady
  7. if ( readyList ) {
  8. var fn, i = 0;
  9. while ( (fn = readyList[ i++ ]) ) {
  10. fn.call( document, jQuery );
  11. }
  12. readyList = null;
  13. }
  14. if ( jQuery.fn.triggerHandler ) {
  15. jQuery( document ).triggerHandler( "ready" );
  16. }
  17. }
  18. }
 ready: function() {
if ( !jQuery.isReady ) {
if ( !document.body ) {
return setTimeout( jQuery.ready, 13 );
}
jQuery.isReady = true; //设置isReady
if ( readyList ) {
var fn, i = 0;
while ( (fn = readyList[ i++ ]) ) {
fn.call( document, jQuery );
}
readyList = null;
}
if ( jQuery.fn.triggerHandler ) {
jQuery( document ).triggerHandler( "ready" );
}
}
}

3. bindReady() 绑定事件监听器的方法 屏蔽了浏览器的差异

看看bindReady的实现

Js代码

  1. bindReady: function() {
  2. if ( readyBound ) { //默认为false
  3. return;
  4. }
  5.   readyBound = true;
  6. if ( document.readyState === "complete" ) {
  7. return jQuery.ready();
  8. }
  9. if ( document.addEventListener ) { document.addEventListener("DOMContentLoaded",DOMContentLoaded, false );
  10. window.addEventListener( "load", jQuery.ready, false );
  11. } else if ( document.attachEvent ) {
  12. document.attachEvent("onreadystatechange", DOMContentLoaded);
  13. window.attachEvent( "onload", jQuery.ready );
  14. var toplevel = false;
  15.    try {
  16. toplevel = window.frameElement == null;
  17. } catch(e) {}
  18. if ( document.documentElement.doScroll && toplevel ) {
  19. doScrollCheck();
  20. }
  21. }
  22. }
bindReady: function() {
if ( readyBound ) { //默认为false
return;
}
readyBound = true;
if ( document.readyState === "complete" ) {
return jQuery.ready();
}
if ( document.addEventListener ) { document.addEventListener("DOMContentLoaded",DOMContentLoaded, false );
window.addEventListener( "load", jQuery.ready, false );
} else if ( document.attachEvent ) {
document.attachEvent("onreadystatechange", DOMContentLoaded);
window.attachEvent( "onload", jQuery.ready );
var toplevel = false;
try {
toplevel = window.frameElement == null;
} catch(e) {}
if ( document.documentElement.doScroll && toplevel ) {
doScrollCheck();
}
}
}

4. doScrollCheck() 为IE浏览器测试的方法

doScrollCheck

Js代码

  1. function doScrollCheck() {
  2. if ( jQuery.isReady ) {
  3. return;
  4. }
  5. try {
  6. document.documentElement.doScroll("left");
  7. } catch( error ) {
  8. setTimeout( doScrollCheck, 1 );
  9. return;
  10. }
  11. //不停的执行document.documentElement.doScroll("left")
  12. jQuery.ready();
  13. }
function doScrollCheck() {
if ( jQuery.isReady ) {
return;
}
try {
document.documentElement.doScroll("left");
} catch( error ) {
setTimeout( doScrollCheck, 1 );
return;
}
//不停的执行document.documentElement.doScroll("left")
jQuery.ready();
}

4. DOMContentLoaded() 移除了绑定的DOMContentLoaded监听器,并且调用jQuery.ready()方法

源码展示:

Js代码

  1. DOMContentLoaded = function() {
  2. document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
  3. jQuery.ready();
  4. };
DOMContentLoaded = function() {
document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
jQuery.ready();
};

参考下面文章:

http://www.javaeye.com/topic/818329#1767310