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 相关文章推荐
js左右弹性滚动对联广告代码分享
Feb 19 Javascript
利用jquery动画特效和css打造的侧边弹出垂直导航
Apr 04 Javascript
jquery遍历函数siblings()用法实例
Dec 24 Javascript
基于JS代码实现实时显示系统时间
Jun 16 Javascript
JS模拟实现方法重载示例
Aug 03 Javascript
D3.js实现文本的换行详解
Oct 14 Javascript
JS使用tween.js动画库实现轮播图并且有切换功能
Jul 17 Javascript
Vue render渲染时间戳转时间,时间转时间戳及渲染进度条效果
Jul 27 Javascript
Spring boot 和Vue开发中CORS跨域问题解决
Sep 05 Javascript
JavaScript使用类似break机制中断forEach循环的方法
Nov 13 Javascript
vue多层嵌套路由实例分析
Mar 19 Javascript
浅谈vue使用axios的回调函数中this不指向vue实例,为undefined
Sep 21 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代码
2008/09/10 PHP
php解决约瑟夫环示例
2014/04/09 PHP
ThinkPHP中url隐藏入口文件后接收alipay传值的方法
2014/12/09 PHP
PHP中你应该知道的require()文件包含的正确用法
2015/06/12 PHP
thinkPHP中volist标签用法示例
2016/12/06 PHP
PHP simplexml_import_dom()函数讲解
2019/02/03 PHP
php pdo连接数据库操作示例
2019/11/18 PHP
JavaScript 函数式编程的原理
2009/10/16 Javascript
jQuery+ajax实现顶一下,踩一下效果
2010/07/17 Javascript
jQuery timers计时器简单应用说明
2010/10/28 Javascript
详解Javascript动态操作CSS
2014/12/08 Javascript
jquery实现右键菜单插件
2015/03/29 Javascript
详解JavaScript的回调函数
2015/11/20 Javascript
基于MVC4+EasyUI的Web开发框架形成之旅之界面控件的使用
2015/12/16 Javascript
让你彻底掌握es6 Promise的八段代码
2017/07/26 Javascript
Angularjs Ng_repeat中实现复选框选中并显示不同的样式方法
2018/09/12 Javascript
vue使用vuex实现首页导航切换不同路由的方法
2019/05/08 Javascript
jQuery带控制按钮轮播图插件
2020/07/31 jQuery
three.js 制作动态二维码的示例代码
2020/07/31 Javascript
浅谈鸿蒙 JavaScript GUI 技术栈
2020/09/17 Javascript
python实现图像识别功能
2018/01/29 Python
python3下使用cv2.imwrite存储带有中文路径图片的方法
2018/05/10 Python
详解python的sorted函数对字典按key排序和按value排序
2018/08/10 Python
Python实现猜年龄游戏代码实例
2020/03/25 Python
Python + selenium + crontab实现每日定时自动打卡功能
2020/03/31 Python
python nohup 实现远程运行不宕机操作
2020/04/16 Python
keras用auc做metrics以及早停实例
2020/07/02 Python
Python面向对象多态实现原理及代码实例
2020/09/16 Python
css3选择器基本介绍
2014/12/15 HTML / CSS
初探CSS3中的calc()功能
2015/07/14 HTML / CSS
经营理念口号
2014/06/21 职场文书
大学生就业意向书
2015/05/11 职场文书
2015年度合同管理工作总结
2015/05/22 职场文书
公司催款律师函
2015/05/27 职场文书
宝宝满月宴答谢词
2015/09/30 职场文书
MySQL创建管理KEY分区
2022/04/13 MySQL