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 - 如何引入js代码
Mar 09 Javascript
关于COOKIE个数与大小的问题
Jan 17 Javascript
JQuery中attr属性和jQuery.data()学习笔记【必看】
May 18 Javascript
关于javascript事件响应的基础语法总结(必看篇)
Dec 26 Javascript
简单的JS控制button颜色随点击更改的实现方法
Apr 17 Javascript
基于Vue实例生命周期(全面解析)
Aug 16 Javascript
Js利用prototype自定义数组方法示例
Oct 20 Javascript
Vue-router路由判断页面未登录跳转到登录页面的实例
Oct 26 Javascript
jQuery简单实现对数组去重及排序操作实例
Oct 31 jQuery
AngularJS动态添加数据并删除的实例
Feb 27 Javascript
微信小程序WebSocket实现聊天对话功能
Jul 06 Javascript
vue-quill-editor的使用及个性化定制操作
Aug 04 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中cookie的作用域
2008/03/27 PHP
PHP可变函数的使用详解
2013/06/14 PHP
PHP实现的封装验证码类详解
2013/06/18 PHP
浅析php插件 Simple HTML DOM 用DOM方式处理HTML
2013/07/01 PHP
PHP 获取远程文件大小的3种解决方法
2013/07/11 PHP
使用PHP编写的SVN类
2013/07/18 PHP
Server.HTMLEncode让代码在页面里显示为源代码
2013/12/08 PHP
JS中简单的实现像C#中using功能(有源码下载)
2007/01/09 Javascript
JavaScript面向对象之体会[总结]
2008/11/13 Javascript
jquery win 7透明弹出层效果的简单代码
2013/08/06 Javascript
JavaScript实现给定时间相加天数的方法
2016/01/25 Javascript
基于jQuery实现火焰灯效果导航菜单
2017/01/04 Javascript
前端Vue项目详解--初始化及导航栏
2019/06/24 Javascript
python实现去除下载电影和电视剧文件名中的多余字符的方法
2014/09/23 Python
python进程类subprocess的一些操作方法例子
2014/11/22 Python
深入浅析python继承问题
2016/05/29 Python
Python编写登陆接口的方法
2017/07/10 Python
好的Python培训机构应该具备哪些条件
2018/05/23 Python
python中多个装饰器的执行顺序详解
2018/10/08 Python
python中列表的切片与修改知识点总结
2019/07/23 Python
解决python web项目意外关闭,但占用端口的问题
2019/12/17 Python
Python变量、数据类型、数据类型转换相关函数用法实例详解
2020/01/09 Python
pytorch实现seq2seq时对loss进行mask的方式
2020/02/18 Python
Numpy一维线性插值函数的用法
2020/04/22 Python
Python生成pdf目录书签的实例方法
2020/10/29 Python
Python Unittest原理及基本使用方法
2020/11/06 Python
如何基于Python pygame实现动画跑马灯
2020/11/18 Python
VSCode 自定义html5模板的实现
2019/12/05 HTML / CSS
阿迪达斯丹麦官网:adidas丹麦
2016/10/01 全球购物
Sunglasses Shop荷兰站:英国最大的太阳镜独立在线零售商和供应商
2017/01/08 全球购物
J.Crew官网:美国知名休闲服装品牌
2017/05/19 全球购物
优秀少先队辅导员先进事迹材料
2014/05/18 职场文书
如何写求职信
2014/05/24 职场文书
普通党员个人对照检查材料
2014/09/18 职场文书
Redis 常见使用场景
2021/08/30 Redis
MySQL实现配置主从复制项目实践
2022/03/31 MySQL