jQuery版本:2.0.3

DOM加载有关的扩展

  • isReady:DOM是否加载完(内部使用)
  • readyWait:等待多少文件的计数器(内部使用)
  • holdReady():推迟DOM触发
  • ready():准备DOM触发。
  • jQuery.ready.promise=function(){};  监听DOM的异步操作(内部使用)

一、$(function(){})和原生window.onload的关系

这个在面试中也是经常会被问到的。从下面几个角度来分析一下它们的区别

1、执行时机

页面加载,先加载节点,再加载文件,比如img文件,flash等。

$(function(){})DOM加载完执行。可能DOM元素关联的东西并没有加载完。

window.onload等节点和文件都加载完执行。

对应的事件监听

jQuery用的是DOMContentLoaded事件。

DOMDContentLoaded:原生DOM加载事件,这个事件触发代表DOM加载完了。

我之前写过一篇文章的页面加载时间分析里也有提到。

onload对应的是load事件。

2、个数

window.onload不能写多个,后面的会覆盖前面的。

$(function(){})可以写多个。都会执行 。

3、简化写法

$(function(){})是$(document) .ready(function(){});的简化写法。

window.onload没有简化写法。

二、jQurey如何实现DOM ready的

jQuery直接调用DOMContentLoaded来实现DOM的ready。但是DOMContentLoaded和onLoad一样,浏览器只执行一次,jQuery用什么判断是否已经执行过呢?document.readyState就是判断这个的依据。

readyState是document的属性,总共有3个值:

  • loading:文档正在加载中
  • interactive:文档已经加载完成,正在进行css和图片等资源的加载
  • complete:文档的所以资源加载完成

判断完之后如何回调呢?就是用Promise。jQuery通过new一个$.Deferred(promise)对象来实现对DOM的ready的回调,在DOMContentLoaded中将这个promise给resolve掉,这样就执行了之前注册的回调函数,同时后面新注册的回调也会立刻执行。

但是在调用promise之前,jQuery执行了一次setTimeout,因为jQuery.Promise是不会产生异步的,这和标准的promise规范是不一样的,所有jQuery自己又手动做了一次setTimeout来实现异步。这样使得无论使用在DOM的ready之前注册的回调还是之后注册的回调都会在异步中执行。

三、源码整体实现逻辑

$(fn)==>new一个 jQuery.fn.init(fn)==>返回$(document).ready( fn)。也就是说

  • $(function(){}) =》
  • 调用$(document).ready(function(){})=》
  • 相当于$().ready(fn)实例方法=》
  • 调用的jQuery.ready.promise().done(fn)=》
  • jQuery.ready.promise中不管if还是else最终都是调用jQuery.ready(),并返回promise=》
  • jQuery.ready()里面重点是readyList.resolveWith( document, [ jQuery ] );已完成。至此DOM加载完毕就可以调用fn了。

四、实现细节

1、重点是:jQuery.ready.promise()方法【巧妙

如果DOM已经加载完成了,调用jQuery.ready()这个工具方法;

如果DOM没加载完,监听DOMContentLoaded事件和load事件,等事件发生时回调completed(),最终也是调用jQuery.ready()这个工具方法;

var    // A central reference to the root jQuery(document)
    rootjQuery,// The deferred used on DOM ready
    readyList;jQuery.ready.promise = function( obj ) {if ( !readyList ) { //第一次readyList为空可以进来,后续就进不来if了,只执行一次
readyList = jQuery.Deferred(); //第一步,创建延迟对象if ( document.readyState === "complete" ) { //DOM加载完成的标志就是document.readyState为complete,如果DOM已经加载好了就直接调工具方法jQuery.ready。setTimeout( jQuery.ready );//加定时器是为了兼容IE} else {//DOM没有加载完检测,即检测了DOMContentLoaded事件,也检测了load事件;最终走回调completed函数// Use the handy event callbackdocument.addEventListener( "DOMContentLoaded", completed, false );// A fallback to window.onload, that will always workwindow.addEventListener( "load", completed, false ); //因为火狐浏览器会缓存load事件,为了第一时间相应所以对load也监听了
        }}return readyList.promise( obj );
};

completed回调函数如下,最终调用的也是jQuery.ready()。

    // The ready event handler and self cleanup methodcompleted = function() {//不管是DOMContentLoaded事件还是load发生,都会取消2个事件监听//jQuery.ready()只会触发一次document.removeEventListener( "DOMContentLoaded", completed, false );window.removeEventListener( "load", completed, false );jQuery.ready();};

2、jQuery.ready()工具方法做了些什么

先做个测试:

   $(function(arg){alert(this); //[object HTMLDocument]alert(arg); //jQuery函数})

再做个测试:

除了$(function(){});$(document).ready(function(){}),也可以把ready当做事件来处理如下。

<script>
$(document).on("ready",function(){alert(123); //123
});
</script>

之所以会自动弹出123,是因为在jQuery源码中用这句话jQuery( document ).trigger("ready").off("ready");来主动触发了ready事件,触发后再取消掉。

// Handle when the DOM is ready
ready: function( wait ) { //参数和holdReady有关// Abort if there are pending holds or we're already readyif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {return;}// Remember that the DOM is readyjQuery.isReady = true;// If a normal DOM Ready event fired, decrement, and wait if need beif ( wait !== true && --jQuery.readyWait > 0 ) {return;}//第一步看这里重点,resolveWith改变状态的时候传参了,给done中方法fn传入了参数,//document是fn的this指向,jQuery是参数// If there are functions bound, to execute
    readyList.resolveWith( document, [ jQuery ] );//跟主动触发有关// Trigger any bound ready eventsif ( jQuery.fn.trigger ) {jQuery( document ).trigger("ready").off("ready");}
},

跟ready的参数有关的有一个holdReady()。

先做个测试

$.holdReady(true);
$(function () {alert(123); //调用了holdReady并传参true,就不能弹出123了
});

可以推迟,也可以释放推迟,释放了以后就可以触发了。

$.holdReady(true);
$.holdReady(false);
$(function () {alert(123); //释放了holdReady,就弹出123
});

这个有什么用?

比如:

$.getScript('js/a.js',function(){ //异步加载,不会影响后续代码执行。可能会产生一个问题,alert(2)先执行了a.js还没有加载完

})$(function () {alert(2);//先弹2,后弹出1
});

很多时候引入外部文件的时候,都想等外部文件或者插件加载完,再去触发操作,操作可能用到a.js。现在这个顺序不对,会出问题。

怎样解决这个问题?用holdReady()方法。

    $.holdReady(true); //在这里先hold住$.getScript('js/a.js', function () { //异步加载,不会影响后续代码执行。可能会产生一个问题,alert(2)先执行了a.js还没有加载完$.holdReady(false); //加载完释放,不hold了就可以弹2了
    })$(function () {alert(2);//先弹2,后弹出1});

再深入一点,holdReady() 要针对的文件可能不止一个,有很多个,所以要等所有的文件都加载完再执行,所以源码中有一个计数的readyWait。

源码中定义了一个等待栈变量——readyWait,每次执行$.holdReady(true)都会增加压栈,而每次$.holdReady()执行都会弹栈,等空栈的时候就执行jQuery.ready函数,即将promise给resolve掉。

// Is the DOM ready to be used? Set to true once it occurs.
isReady: false,
// A counter to track how many items to wait for before
// the ready event fires. See #6781
readyWait: 1,//第二步看这里
//holdReady推迟DOM的触发
// Hold (or release) the ready event
holdReady: function( hold ) {if ( hold ) {jQuery.readyWait++;//hold为真,让readyWait加加处理} else {jQuery.ready( true );}
},// Handle when the DOM is ready
ready: function( wait ) { //参数和holdReady有关// Abort if there are pending holds or we're already ready//readyWait为0时就不用hold了,执行后面的操作if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { return;}// Remember that the DOM is readyjQuery.isReady = true; //默认是false// If a normal DOM Ready event fired, decrement, and wait if need beif ( wait !== true && --jQuery.readyWait > 0 ) {return;}//第一步看这里重点,resolveWith改变状态的时候传参了,给done中方法fn传入了参数,//document是fn的this指向,jQuery是参数// If there are functions bound, to execute
    readyList.resolveWith( document, [ jQuery ] );//跟主动触发有关// Trigger any bound ready eventsif ( jQuery.fn.trigger ) {jQuery( document ).trigger("ready").off("ready");}
},

刚开始看源码,很多地方理解也不到位,解释可能也不清楚。

参考:

http://www.cnblogs.com/aeexiaoqiang/p/6525702.html

本文作者starof,因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处:http://www.cnblogs.com/starof/p/6856572.html有问题欢迎与我讨论,共同进步。

转载于:https://www.cnblogs.com/starof/p/6856572.html

jquery源码 DOM加载相关推荐

  1. jQuery源码dom ready分析

    一.前言 在平时开发web项目时,我们使用jquery框架时,可能经常这样来使用$(document).ready(fn),$(function(){}),这样使用的原因是在浏览器把DOM树渲染好之前 ...

  2. jQuery deferred应用dom加载完毕详细源码分析(三)

    我承认上章ajax部分写得不好,不要怪我,它的ajax代码太多了,而且跨越大,方法跳跃多,实在不好排版与讲解,但如果你真正想研究源码并且仔细读了得话,你的 收获应该会很大,至少你明白了js的ajax是 ...

  3. 剖析Spring源码:加载IOC容器

    本文接上一篇文章 阅读Spring源码:IOC控制反转前的处理,继续进行下面的分析 首先贴出 Spring bean容器的刷新的核心 11个步骤进行祭拜(一定要让我学会了-阿门) // 完成IoC容器 ...

  4. Glide源码解析-加载流程

    1 引言 一直想要阅读Glide源码,但是苦于时间和功力都不够,总是断断续续的,趁着现在有一些空暇时间,来简要分析Glide的源码.Glide的实现太过复杂,不可能做到面面俱到,如果每一行都细致分析, ...

  5. jquery中DOM加载事件,onload事件和ready事件

    全栈工程师开发手册 (作者:栾鹏) jquery系列教程4-事件操作全解 jquery中DOM加载事件 jquery中的DOM加载事件分为onload事件和ready事件.,具体功能如代码中注释. 代 ...

  6. jQuery源码解析(3)—— ready加载、queue队列

    ready.queue放在一块写,没有特殊的意思,只是相对来说它俩可能源码是最简单的了.ready是在dom加载完成后,以最快速度触发,很实用.queue是队列,比如动画的顺序触发就是通过默认队列'f ...

  7. echarts asp mysql 源码_如何使用PHP+jQuery+MySQL实现异步加载ECharts地图数据(附源码下载)...

    ECharts地图主要用于地理区域数据的可视化,展示不同区域的数据分布信息.ECharts官网提供了中国地图.世界地图等地图数据下载,通过js引入或异步加载json文件的形式调用地图. 本文将结合实例 ...

  8. jQuery:等页面DOM加载完毕后再执行代码

    等着页面DOM加载完毕后再执行代码 第一种方式(比较麻烦,不常用): $(document).ready(function(){ - }) 第二种方式(常用): $(function(){ - }) ...

  9. jQuery源码研究学习笔记(二)

    jQuery总体架构: jQuery模块可以大致分为三部分:入口模块.底层支持模块.功能模块. 参考jQuery技术内幕解析 jquery源码总体架构: (function(window,undefi ...

最新文章

  1. 在 Google Colab 中使用 OpenCV 进行图像处理简介
  2. 一个关于在Fedora下安装jdk的问题
  3. Tomcat6下使用jBPM-4出现 java.lang.LinkageError。javax/el/ExpressionFactory解决办法
  4. webstorm的安装
  5. 项目管理(3):备战pmp
  6. JavaScript类与原型——组织JavaScript代码
  7. 禁用行、列、单元格单元格编辑
  8. linux重启网卡命令_如何在 Linux 中更改 MAC 地址 | Linux 中国
  9. 实践 | 图片文本爬虫与数据分析
  10. MAC删除自带ABC输入法
  11. 数码管与74HC573,74HC138电路
  12. PayPal接口开发
  13. AVL树(动图详解)
  14. day01 pathon基础
  15. U盘中毒文件都不见了
  16. 基于微信云开发的商家转账至零钱
  17. 如何使用 LK 字幕脚本工具
  18. 简单又详细的网页爬虫案例
  19. 鼠标事件,显示悬浮窗
  20. 计算机毕设之超市积分管理系统

热门文章

  1. apache 访问出现403 Forbidden
  2. Linux文件目录结构2
  3. 【翻译】Ext JS 4.2介绍
  4. ASP.NET夜话笔记06
  5. 家园签到:无忧币天天送,连续领礼更多!【家园帮助】
  6. Windows下Git上传项目代码记录
  7. Linux大文件切割命令split
  8. Linux操作系统Ubuntu部署Mysql篇
  9. 服务器linux系统支持php好,关于Linux服务器系统的七大优势,你知道几个?
  10. 类加载子系统的详解——未完待续