Jquery1.9.1源码分析系列(六)延时对象应用之jQuery.ready


Posted in Javascript onNovember 24, 2015

还记不记得jQuery初始化函数jQuery.fn.init中有这样是一个分支

//document ready简便写法$(function(){…})
} else if ( jQuery.isFunction( selector ) ) {
 return rootjQuery.ready( selector );
}
所以$(fn)===$(document).ready(fn)。

来看一下jQuery.fn.ready的源码
ready: function( fn ) {
 // Add the callback
 jQuery.ready.promise().done( fn );
 return this;
}

很明显在jQuery.ready.promise函数中设置了延时,当延时对象解决的时候执行fn函数。

主要的处理流程:

创建一个延时对象,并将文档准备好后的处理事件添加到该延时对象成功事件列表上。

jQuery.ready.promise = function( obj ) {
if ( !readyList ) {


readyList = jQuery.Deferred();


...

}
 return readyList.promise( obj );
}

添加文档准备状态的监听函数(jQuery.ready.promise函数片段)

//标准浏览器支持DOMContentLoaded事件
 } else if ( document.addEventListener ) {
   //绑定DOMContentLoaded事件和响应函数,响应函数会解决延时
   document.addEventListener( "DOMContentLoaded", completed, false );
   //回退到window.onload事件绑定,所有的浏览器都支持
   window.addEventListener( "load", completed, false );
 //如果是IE事件模型
 } else {
   //确保在onload之前执行延时,可能时间比较迟,但是对于iframes来说比较安全
   document.attachEvent( "onreadystatechange", completed );
   //回退到window.onload事件绑定,所有的浏览器都支持
   window.attachEvent( "onload", completed );
   //如果IE并且不是一个frame
   //不断地检查,看是否该文件已准备就绪
   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();
      //执行延迟
      jQuery.ready();
     }
    })();
   }
  }

一旦监听到文档准备完成,则调用jQuery.ready执行延时对象的成功回调列表:即所有通过jQuery.ready(fn)【或jQuery(fn)】方式添加的函数fn。

//ready事件处理函数
completed = function( event ) {
 // readyState === "complete"在老版本IE上适用
 if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
  detach();
  jQuery.ready();
 }
},
//清除ready事件绑定
detach = function() {
 if ( document.addEventListener ) {
  document.removeEventListener( "DOMContentLoaded", completed, false );
  window.removeEventListener( "load", completed, false );
 } else {
  document.detachEvent( "onreadystatechange", completed );
  window.detachEvent( "onload", completed );
 }
};

//处理当DOM准备完成
jQuery.ready: function( wait ) {  

 ... 

 

 //设置DOM已经准备好的标志 
 

 jQuery.isReady = true; 

 ... 

 //执行绑定的延时事件 

 readyList.resolveWith( document, [ jQuery ] ); 

 //触发任何绑定的就绪事件 

 if ( jQuery.fn.trigger ) { 


  jQuery( document ).trigger("ready").off("ready"); 

 } 
}

 

整个过程就是如此。其中有一些小的知识点整理一下。

a. 文档加载状态document.readyState

document.readyState用来判断文档加载状态,是一个只读属性,可能的值有:

0-uninitialized:XML 对象被产生,但没有任何文件被加载。

1-loading:加载程序进行中,但文件尚未开始解析。

2-loaded:部分的文件已经加载且进行解析,但对象模型尚未生效。

3-interactive:仅对已加载的部分文件有效,在此情况下,对象模型是有效但只读的。

4-complete:文件已完全加载,代表加载成功。

实例:

document.onreadystatechange = stateChange;//当页面加载状态改变的时候执行这个方法.
function stateChange() { 

if(document.readyState == "complete"){ //当页面加载状态为完全结束时进入 




alert("文档加载成功") 


} 
}

但是,老版本的Firefox并不支持document.readyState【最新的Firefox已经支持了】。所以想要兼容所有浏览器监听文档准备完成分两种情况来处理:

- 标准浏览器使用addEventListener添加DOMContentLoaded和load监听,任何一个事件被触发即可

- 老版本IE浏览器使用attachEvent添加onreadystatechange和onload来监听,任何一个被触发,并且onreadystatechange时document.readyState === "complete"即可。

  jQuery的处理也就是如此了

jQuery.ready.promise = function(){
...

//标准浏览器支持DOMContentLoaded事件

else if ( document.addEventListener ) {
   //绑定DOMContentLoaded事件和响应函数,响应函数会解决延时
   document.addEventListener( "DOMContentLoaded", completed, false );
   //回退到window.onload事件绑定,所有的浏览器都支持
   window.addEventListener( "load", completed, false );
 //如果是IE事件模型
 } else {
   //确保在onload之前执行延时,可能时间比较迟,但是对于iframes来说比较安全
   document.attachEvent( "onreadystatechange", completed );
   //回退到window.onload事件绑定,所有的浏览器都支持
   window.attachEvent( "onload", completed );



 ...

}
}
//ready事件处理函数
completed = function( event ) {
 // readyState === "complete"在老版本IE上适用
 if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
  detach();
  jQuery.ready();
 }
}

b.doScroll检测文档加载完成

这是Diego Perini 发现的一种检测IE是否加载完成的方式。详细链接

原理是当页面 DOM 未加载完成时调用 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();
      //执行延迟
      jQuery.ready();
     }
    })();

以上所述是三水点靠木小编给大家介绍的Jquery1.9.1源码分析系列(六)延时对象应用之jQuery.ready的全部内容,希望大家喜欢。

Javascript 相关文章推荐
获取JavaScript用户自定义类的类名称的代码
Mar 08 Javascript
String.prototype实现的一些javascript函数介绍
Nov 22 Javascript
JS实现带缓冲效果打开、关闭、移动一个层的方法
May 09 Javascript
JavaScript实现输入框(密码框)出现提示语
Jan 12 Javascript
jQuery 实现评论等级好评差评特效
May 06 Javascript
Vue结合原生js实现自定义组件自动生成示例
Jan 21 Javascript
微信小程序页面间通信的5种方式
Mar 31 Javascript
js-FCC算法-No repeats please字符串的全排列(详解)
May 02 Javascript
AngularJS入门教程二:在路由中传递参数的方法分析
May 27 Javascript
js实现图片推拉门效果代码实例
May 18 Javascript
详解Jest结合Vue-test-utils使用的初步实践
Jun 27 Javascript
分享JS表单验证源码(带错误提示及密码等级)
Jan 05 Javascript
如何解决ligerUI布局时Center中的Tab高度大小
Nov 24 #Javascript
JS实现图片高亮展示效果实例
Nov 24 #Javascript
JS截取字符串实例详解
Nov 24 #Javascript
超漂亮的jQuery图片轮播特效
Nov 24 #Javascript
jquery实现移动端点击图片查看大图特效
Sep 11 #Javascript
jquery解析json格式数据的方法(对象、字符串)
Nov 24 #Javascript
Bootstrap每天必学之按钮(一)
Nov 24 #Javascript
You might like
一个oracle+PHP的查询的例子
2006/10/09 PHP
global.php
2006/12/09 PHP
PHP实现用户异地登录提醒功能的方法【基于thinkPHP框架】
2018/03/15 PHP
PHP常用的类封装小结【4个工具类】
2019/06/28 PHP
JavaScript原型继承之基础机制分析
2011/08/26 Javascript
Extjs中ComboBox加载并赋初值的实现方法
2012/03/22 Javascript
jquery 鼠标滑动显示详情应用示例
2014/01/24 Javascript
js模拟hashtable的简单实例
2014/03/06 Javascript
jQuery中prependTo()方法用法实例
2015/01/08 Javascript
jQuery实现滑动页面固定顶部显示(可根据显示位置消失与替换)
2015/10/28 Javascript
JS动态增删表格行的方法
2016/03/03 Javascript
javascript检查某个元素在数组中的索引值
2016/03/30 Javascript
JQuery的常用选择器、过滤器、方法全面介绍
2016/05/25 Javascript
JS实现的自定义显示加载等待图片插件(loading.gif)
2016/06/17 Javascript
JS路由跳转的简单实现代码
2017/09/21 Javascript
nodejs读取图片返回给浏览器显示
2019/07/25 NodeJs
layui固定下拉框的显示条数(有滚动条)的方法
2019/09/10 Javascript
js判断在哪个浏览器打开项目的方法
2020/01/21 Javascript
Vue使用JSEncrypt实现rsa加密及挂载方法
2020/02/07 Javascript
JavaScript实现密码强度实时验证
2020/03/18 Javascript
JavaScript实现HSL拾色器
2020/05/21 Javascript
Nodejs环境实现socket通信过程解析
2020/07/03 NodeJs
nuxt 路由、过渡特效、中间件的实现代码
2020/11/06 Javascript
Python中类的继承代码实例
2014/10/28 Python
Python-Tkinter Text输入内容在界面显示的实例
2019/07/12 Python
python3 批量获取对应端口服务的实例
2019/07/25 Python
基础的CSS3弹性盒Flexbox布局使用实例
2016/04/08 HTML / CSS
当当网官方旗舰店:中国图书销售夺金品牌
2018/04/02 全球购物
莱德杯高尔夫欧洲官方商店:Ryder Cup Shop
2019/08/14 全球购物
北京振戎融通Java面试题
2015/09/03 面试题
房产销售经理职责
2013/12/20 职场文书
婚前协议书
2014/04/15 职场文书
医德医魂心得体会
2014/09/11 职场文书
先进学校事迹材料
2014/12/30 职场文书
通报表扬范文
2015/01/17 职场文书
日本读研:怎样写好一篇日本研究计划书?
2019/07/15 职场文书