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中的escape及unescape函数的php实现代码
Sep 04 Javascript
jQuery弹性滑动导航菜单实现思路及代码
May 02 Javascript
基于JavaScript实现下拉列表左右移动代码
Feb 07 Javascript
学习使用jQuery表单验证插件和日历插件
Feb 13 Javascript
微信小程序实现缓存根据不同的id来进行设置和读取缓存
Jun 12 Javascript
vue实现表格增删改查效果的实例代码
Jul 18 Javascript
jQuery实现表格冻结顶栏效果
Aug 20 jQuery
vue计算属性computed的使用方法示例
Mar 13 Javascript
JavaScript前端页面搜索功能案例【基于jQuery】
Jul 10 jQuery
jQuery实现弹出层效果
Dec 10 jQuery
微信jssdk踩坑之签名错误invalid signature
May 19 Javascript
解决vue项目打包上服务器显示404错误,本地没出错的问题
Nov 03 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获取MSN好友列表类的实现代码
2013/06/23 PHP
在PHP中使用X-SendFile头让文件下载更快
2014/06/01 PHP
php上传文件常见问题总结
2015/02/03 PHP
完美利用Yii2微信后台开发的系列总结
2016/07/18 PHP
php实现购物车功能(以大苹果购物网为例)
2017/03/09 PHP
Laravel接收前端ajax传来的数据的实例代码
2017/07/20 PHP
jquery 多行文本框(textarea)高度变化
2013/07/03 Javascript
js文件缓存之版本管理详解
2013/07/05 Javascript
细说javascript函数从函数的构成开始
2013/08/29 Javascript
导入extjs、jquery 文件时$使用冲突问题解决方法
2014/01/14 Javascript
js获取当前页面的url网址信息
2014/06/12 Javascript
jQuery实现的数值范围range2dslider选取插件特效多款代码分享
2015/08/27 Javascript
JS验证邮件地址格式方法小结
2015/12/01 Javascript
JS使用正则表达式过滤多个词语并替换为相同长度星号的方法
2016/08/03 Javascript
React-Native左右联动List的示例代码
2017/09/21 Javascript
jQuery pjax 应用简单示例
2018/09/20 jQuery
解决vue的过渡动画无法正常实现问题
2019/10/31 Javascript
electron踩坑之remote of undefined的解决
2020/10/06 Javascript
[37:23]DOTA2上海特级锦标赛主赛事日 - 3 胜者组第二轮#2Secret VS EG第二局
2016/03/04 DOTA
python解析基于xml格式的日志文件
2017/02/25 Python
python互斥锁、加锁、同步机制、异步通信知识总结
2018/02/11 Python
Python如何抓取天猫商品详细信息及交易记录
2018/02/23 Python
Python Numpy 实现交换两行和两列的方法
2019/06/26 Python
ORM Django 终端打印 SQL 语句实现解析
2019/08/09 Python
python实现文件的分割与合并
2019/08/29 Python
基于python操作ES实例详解
2019/11/16 Python
python 实现单通道转3通道
2019/12/03 Python
numpy 矩阵形状调整:拉伸、变成一位数组的实例
2020/06/18 Python
python uuid生成唯一id或str的最简单案例
2021/01/13 Python
详解Html5 监听拦截Android返回键方法
2018/04/18 HTML / CSS
Clarks英国官方网站:全球领军鞋履品牌
2016/11/26 全球购物
Python里面如何实现tuple和list的转换
2012/06/13 面试题
大学生实习证明范本
2014/01/15 职场文书
大学团日活动新闻稿
2014/09/10 职场文书
Vue OpenLayer测距功能的实现
2022/04/20 Vue.js
win10拖拽文件时崩溃怎么解决?win10文件不能拖拽问题解决方法
2022/08/14 数码科技