jQuery  ready方法实现原理详解


Posted in Javascript onOctober 19, 2016

今天闲来无事研究研究jQuery.ready()的内部实现,看JQ的源码一头雾水,由于自己很菜了,于是翻了翻牛人的播客,讲述详细,收获颇多。

先普及一下jquery.ready()和window.onload,window.onload事件是在页面所有的资源都加载完毕后触发的. 如果页面上有大图片等资源响应缓慢, 会导致window.onload事件迟迟无法触发.所以出现了DOM Ready事件. 此事件在DOM文档结构准备完毕后触发, 即在资源加载前触发. 

jQuery中的ready方法实现了当页面加载完成后才执行的效果,但他并不是window.onload或者doucment.onload的封装,而是使用 标准W3C浏览器DOM隐藏api和IE浏览器缺陷来完成的,首先,我们来看jQuery的代码

DOMContentLoaded = function()
 {
  //取消事件监听,执行ready方法
 if ( document.addEventListener )
 {   
  document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
  jQuery.ready();
 }
  else if ( document.readyState === "complete" ) 
 {
  document.detachEvent( "onreadystatechange", DOMContentLoaded );
  jQuery.ready();
 }
};
jQuery.ready.promise = function( obj ) {
 if ( !readyList ) {

  readyList = jQuery.Deferred();
   //表示页面已经加载完成,直接调用 ready方法
  if ( document.readyState === "complete" ) { 
   //将 jQuery.ready压入异步消息队列,设置延迟时间1毫秒(注意,有些浏览器延迟不能小于4毫秒)
   setTimeout( jQuery.ready); 
  } 
  else if ( document.addEventListener ) //
  {
    //监听DOM加载完成
   document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
    //这里是为了确保所有ready执行结束,如果DOMContentLoaded方法执行了,将有一个状态值 isReady被设置为true,因此,
    //ready方法一旦执行,那么将只执行一次,window.addEventListener中的ready 将被 return 中断
   window.addEventListener( "load", jQuery.ready, false );
 
  } else {
   //低版本的IE浏览器
   document.attachEvent( "onreadystatechange", DOMContentLoaded );
   window.attachEvent( "onload", jQuery.ready );

   var top = false;

   try {
    top = window.frameElement == null && document.documentElement;
   } catch(e) {}

   if ( top && top.doScroll ) //剔除iframe的成分
   {
    (function doScrollCheck() {
     if ( !jQuery.isReady ) {

      try {
       //根据bug来兼容低版本的IE http://javascript.nwbox.com/IEContentLoaded/
       top.doScroll("left");
      } catch(e) {
       //由于低版本的IE 浏览器,onreadystatechange事件不可靠,因此需要根据各个bug来判断页面是否已加载完成
       return setTimeout( doScrollCheck, 50 ); 
      }

      jQuery.ready();
     }
    })();
   }
  }
 }
 return readyList.promise( obj );
};
ready: function( wait )
 {

 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { 
  //判断页面是否已完成加载并且是否已经执行ready方法
  return;
 }


 if ( !document.body ) {
  return setTimeout( jQuery.ready );
 }

  
 jQuery.isReady = true; //指示ready方法已被执行

  
 if ( wait !== true && --jQuery.readyWait > 0 ) {
  return;
 }

  
 readyList.resolveWith( document, [ jQuery ] );

  
 if ( jQuery.fn.trigger ) {
  jQuery( document ).trigger("ready").off("ready"); 
 }
},

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
javascript 支持链式调用的异步调用框架Async.Operation
Aug 04 Javascript
在父页面调用子页面的JS方法
Sep 29 Javascript
javascript实现动态侧边栏代码
Feb 19 Javascript
使用javascript实现监控视频播放并打印日志
Jan 05 Javascript
jQuery使用slideUp方法实现控制元素缓慢收起
Mar 27 Javascript
学习JavaScript设计模式(继承)
Nov 26 Javascript
JS组件系列之Bootstrap table表格组件神器【二、父子表和行列调序】
May 10 Javascript
扩展Bootstrap Tooltip插件使其可交互的方法
Nov 07 Javascript
jstree单选功能的实现方法
Jun 07 Javascript
微信小程序icon组件使用详解
Jan 31 Javascript
利用webpack理解CommonJS和ES Modules的差异区别
Jun 16 Javascript
谈谈node.js中的模块系统
Sep 01 Javascript
Javascript实现汉字和拼音互转的终极方案
Oct 19 #Javascript
Javascript typeof与instanceof的区别
Oct 18 #Javascript
javascript self对象使用详解
Oct 18 #Javascript
jQuery动态添加与删除tr行实例代码
Oct 18 #Javascript
Jquery表单验证失败后不提交的解决方法
Oct 18 #Javascript
vue.js 表格分页ajax 异步加载数据
Oct 18 #Javascript
vue.js表格分页示例
Oct 18 #Javascript
You might like
PHP+MYSQL会员系统的登陆即权限判断实现代码
2011/09/23 PHP
PHP网站开发中常用的8个小技巧
2015/02/13 PHP
php微信公众号开发之图片回复
2018/10/20 PHP
javascript学习笔记(六) Date 日期类型
2012/06/19 Javascript
在jQuery ajax中按钮button和submit的区别分析
2012/10/07 Javascript
JS cookie中文乱码解决方法
2014/01/28 Javascript
浅谈JS闭包中的循环绑定处理程序
2014/11/09 Javascript
8个超实用的jQuery功能代码分享
2015/01/08 Javascript
jquery实现手机号码选号的方法
2015/07/31 Javascript
Bootstrap创建可折叠的组件
2016/02/23 Javascript
利用Javascript实现BMI计算器
2016/08/16 Javascript
详解nodejs express下使用redis管理session
2017/04/24 NodeJs
jQuery查找dom的几种方法效率详解
2017/05/17 jQuery
react 中父组件与子组件双向绑定问题
2019/05/20 Javascript
解决Layui当中的导航条动态添加后渲染失败的问题
2019/09/25 Javascript
python使用mysqldb连接数据库操作方法示例详解
2013/12/03 Python
python使用rabbitmq实现网络爬虫示例
2014/02/20 Python
代码讲解Python对Windows服务进行监控
2018/02/11 Python
java中的控制结构(if,循环)详解
2019/06/26 Python
详解基于python-django框架的支付宝支付案例
2019/09/23 Python
Python tcp传输代码实例解析
2020/03/18 Python
Python运行提示缺少模块问题解决方案
2020/04/02 Python
Python Flask框架实现简单加法工具过程解析
2020/06/03 Python
html5 Canvas画图教程(3)—canvas出现1像素线条模糊不清的原因
2013/01/09 HTML / CSS
C#如何进行LDAP用户校验
2012/11/21 面试题
AURALog面试题软件测试方面
2013/10/22 面试题
五年级学生评语
2014/04/22 职场文书
幼儿园课题方案
2014/06/09 职场文书
学校社会实践活动总结
2014/07/03 职场文书
会计试用期自我评价
2014/09/19 职场文书
2014年学习委员工作总结
2014/11/14 职场文书
2014年组织委员工作总结
2014/12/01 职场文书
作文批改评语
2014/12/25 职场文书
寒假社会实践个人总结
2015/03/06 职场文书
党组织结对共建协议书
2016/03/23 职场文书
MySQL事务的隔离级别详情
2022/07/15 MySQL