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 相关文章推荐
可拖动窗口,附带鼠标控制渐变透明,开启关闭功能
Jun 26 Javascript
建立良好体验度的Web注册系统ajax
Jul 09 Javascript
JavaScript的面向对象方法以及差别
Mar 31 Javascript
javascript学习笔记(三)显示当时时间的代码
Apr 08 Javascript
jQuery代码优化 事件委托篇
Nov 01 Javascript
jquery中使用$(#form).submit()重写提交表单无效原因分析及解决
Mar 25 Javascript
在Iframe中获取父窗口中表单的值(示例代码)
Nov 22 Javascript
JS实现文字掉落效果的方法
May 06 Javascript
关于cookie的初识和运用(js和jq)
Apr 07 Javascript
JavaScript中push(),join() 函数 实例详解
Sep 06 Javascript
基于JavaScript实现飘落星星特效
Aug 10 Javascript
vue 项目中当访问路由不存在的时候默认访问404页面操作
Aug 31 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
windows下PHP APACHE MYSQ完整配置
2007/01/02 PHP
php 使用post,get的一种简洁方式
2010/04/25 PHP
PHP array_flip() 删除重复数组元素专用函数
2010/05/16 PHP
FireFox浏览器使用Javascript上传大文件
2013/10/30 PHP
使用php测试硬盘写入速度示例
2014/01/27 PHP
php分页函数示例代码分享
2014/02/24 PHP
php判断数组元素中是否存在某个字符串的方法
2014/06/14 PHP
一个实用的php验证码类
2017/07/06 PHP
php类自动装载、链式操作、魔术方法实现代码
2017/07/23 PHP
datePicker——日期选择控件(with jquery)
2007/02/20 Javascript
jQuery取消ajax请求的方法
2015/06/09 Javascript
深入了解JavaScript中的Symbol的使用方法
2015/07/28 Javascript
javascript运动框架用法实例分析(实现放大与缩小效果)
2016/01/08 Javascript
javascript实现全角转半角的方法
2016/01/23 Javascript
使用JQuery 加载页面时调用JS的实现方法
2016/05/30 Javascript
Knockout结合Bootstrap创建动态UI实现产品列表管理
2016/09/14 Javascript
详解angularjs结合pagination插件实现分页功能
2017/02/10 Javascript
Angular.js中angular-ui-router的简单实践
2017/07/18 Javascript
nodejs中密码加密处理操作详解
2018/03/20 NodeJs
vue2.0 实现导航守卫(路由守卫)
2018/05/21 Javascript
Rollup处理并打包JS文件项目实例代码
2018/05/31 Javascript
react-router4按需加载(踩坑填坑)
2019/01/06 Javascript
微信小程序页面间跳转传参方式总结
2019/06/13 Javascript
vue3.0封装轮播图组件的步骤
2021/03/04 Vue.js
[42:11]TNC vs Pain 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
本地文件上传到七牛云服务器示例(七牛云存储)
2014/01/11 Python
Python的randrange()方法使用教程
2015/05/15 Python
python多线程方式执行多个bat代码
2016/06/07 Python
Django框架模板用法入门教程
2019/11/04 Python
解决Python安装cryptography报错问题
2020/09/03 Python
英国足球店:UK Soccer Shop
2017/11/19 全球购物
Emma Bridgewater官网:英国餐具制造商
2019/11/24 全球购物
策划创业计划书
2014/02/06 职场文书
社区党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
董事长助理工作总结2015
2015/07/23 职场文书
Python代码实现双链表
2022/05/25 Python