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 相关文章推荐
prototype 源码中文说明之 prototype.js
Sep 22 Javascript
javascript正则匹配汉字、数字、字母、下划线
Apr 10 Javascript
JavaScript中匿名函数用法实例
Mar 23 Javascript
Jquery基础教程之DOM操作
Aug 19 Javascript
jQuery实现的仿百度,仿谷歌搜索下拉框效果示例
Dec 30 Javascript
jQuery实现div跟随鼠标移动
Aug 20 jQuery
浅谈Angular4实现热加载开发旅程
Sep 08 Javascript
vue源码解析之事件机制原理
Apr 21 Javascript
js根据需要计算数组中重复出现某个元素的个数
Jan 18 Javascript
js 将线性数据转为树形的示例代码
May 28 Javascript
vue学习笔记之Vue中css动画原理简单示例
Feb 29 Javascript
JavaScript canvas实现流星特效
May 20 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新手上路(四)
2006/10/09 PHP
Smarty模板快速入门
2007/01/04 PHP
php简单的留言板与回复功能具体实现
2014/02/19 PHP
php实现可用于mysql,mssql,pg数据库操作类
2014/12/13 PHP
joomla实现注册用户添加新字段的方法
2016/05/05 PHP
PHP 出现 http500 错误的解决方法
2021/03/09 PHP
解决使用attachEvent函数时,this指向被绑定的元素的问题的方法
2007/08/13 Javascript
firefox下frameset取不到值的解决方法
2010/09/06 Javascript
javascript动画浅析
2012/08/30 Javascript
jQuery学习笔记(1)--用jQuery实现异步通信(用json传值)具体思路
2013/04/08 Javascript
JS正则验证邮箱的格式详细介绍
2013/11/19 Javascript
浅谈JavaScript中定义变量时有无var声明的区别
2014/08/18 Javascript
Jquery使用小技巧汇总
2015/12/29 Javascript
简单讲解jQuery中的子元素过滤选择器
2016/04/18 Javascript
微信小程序 参数传递详解
2016/10/24 Javascript
JS使用面向对象技术实现的tab选项卡效果示例
2017/02/28 Javascript
关于bootstrap日期转化,bootstrap-editable的简单使用,bootstrap-fileinput的使用详解
2017/05/12 Javascript
基于jQuery解决ios10以上版本缩放问题
2017/11/03 jQuery
JavaScript实现学生在线做题计时器功能
2018/12/05 Javascript
前端天气插件tpwidget使用方法详解
2019/06/24 Javascript
这应该是最详细的响应式系统讲解了
2019/07/22 Javascript
vue使用better-scroll实现滑动以及左右联动
2020/06/30 Javascript
[05:23]DOTA2-DPC中国联赛2月1日Recap集锦
2021/03/11 DOTA
jupyter notebook中美观显示矩阵实例
2020/04/17 Python
Python中实现输入一个整数的案例
2020/05/03 Python
Python 虚拟环境工作原理解析
2020/12/24 Python
应届毕业生个人自我评价
2013/09/20 职场文书
网络维护管理员的自我评价分享
2013/11/11 职场文书
财务人员求职自荐书范文
2014/02/10 职场文书
社区精神文明建设汇报材料
2014/08/17 职场文书
党的群众路线教育实践活动查摆问题及整改措施
2014/10/10 职场文书
保护校园环境倡议书
2015/04/28 职场文书
安全守法证明
2015/06/23 职场文书
2019年入党思想汇报格式与要求
2019/06/25 职场文书
MySQL下使用Inplace和Online方式创建索引的教程
2021/05/26 MySQL
Mysql表数据比较大情况下修改添加字段的方法实例
2022/06/28 MySQL