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 相关文章推荐
总结AJAX相关JS代码片段和浏览器模型
Aug 15 Javascript
关于eval 与new Function 到底该选哪个?
Apr 17 Javascript
JavaScript中instanceof运算符的用法总结
Nov 19 Javascript
javascript实现json页面分页实例代码
Feb 20 Javascript
纯js和css实现渐变色包括静态渐变和动态渐变
May 29 Javascript
通过XMLHttpRequest和jQuery实现ajax的几种方式
Aug 28 Javascript
基于 Node.js 实现前后端分离
Apr 23 Javascript
简单实现jQuery多选框功能
Jan 09 Javascript
使用ionic在首页新闻中应用到的跑马灯效果的实现方法
Feb 13 Javascript
bootstrap模态框嵌套、tabindex属性、去除阴影的示例代码
Oct 17 Javascript
深入理解 TypeScript Reflect Metadata
Dec 12 Javascript
OpenLayers加载缩放控件使用方法详解
Sep 25 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
PHP写MySQL数据 实现代码
2009/06/15 PHP
php定义数组和使用示例(php数组的定义方法)
2014/03/29 PHP
php面向对象中static静态属性和静态方法的调用
2015/02/08 PHP
PHP异常处理Exception类
2015/12/11 PHP
php设计模式之备忘模式分析【星际争霸游戏案例】
2020/03/24 PHP
javascript 动态调整图片尺寸实现代码
2009/12/28 Javascript
JS Excel读取和写入操作(模板操作)实现代码
2010/04/11 Javascript
超级酷和最实用的jQuery实例收集(20个)
2010/04/21 Javascript
全面了解函数声明与函数表达式、变量提升
2016/08/09 Javascript
js实现table添加行tr、删除行tr、清空行tr的简单实例
2016/10/15 Javascript
AngularJS实现给动态生成的元素绑定事件的方法
2016/12/14 Javascript
jQuery Plupload上传插件的使用
2017/04/19 jQuery
如何理解Vue的v-model指令的使用方法
2018/07/19 Javascript
JS实现查找数组中对象的属性值是否存在示例
2019/05/24 Javascript
JS Ajax请求会话过期处理问题解决方法分析
2019/11/16 Javascript
html中创建并调用vue组件的几种方法汇总
2020/11/17 Javascript
Python自定义类的数组排序实现代码
2016/08/28 Python
Python实现的文本编辑器功能示例
2017/06/30 Python
python django 增删改查操作 数据库Mysql
2017/07/27 Python
对pandas的层次索引与取值的新方法详解
2018/11/06 Python
Windows下Python3.6安装第三方模块的方法
2018/11/22 Python
python3模拟实现xshell远程执行liunx命令的方法
2019/07/12 Python
Django Docker容器化部署之Django-Docker本地部署
2019/10/09 Python
python 常见的反爬虫策略
2020/09/27 Python
详解HTML5新增标签
2017/11/27 HTML / CSS
ECCO爱步美国官网:来自丹麦的鞋履品牌
2016/11/23 全球购物
国外软件测试工程师面试题
2016/12/09 面试题
物流管理毕业生自荐信
2013/10/24 职场文书
财务助理岗位职责
2013/11/10 职场文书
保健品市场营销方案
2014/03/31 职场文书
蛋糕店创业计划书范文
2014/09/21 职场文书
销售人员工作自我评价
2014/09/21 职场文书
2015年春节标语口号
2014/12/09 职场文书
毕业实习指导教师评语
2014/12/31 职场文书
大学三好学生主要事迹范文
2015/11/03 职场文书
MySQL创建高性能索引的全步骤
2021/05/02 MySQL