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

收获应该会很大,至少你明白了js的ajax是怎么回事.不懂得可以继续参阅ajax和Deferred ,其实我更希望你把deferred搞懂了在看这部分.

好吧,言归正传,这次我讲得是$(function(){console.log("dom ready")}); 多么简单的一段代码,但它是在每个浏览器运行的呢?

还是先来个全局展望,会用到以下几个方法,这里你会知道jQuery是真正的hold住哥,因为他要hold dom ready event holdReady,一个神奇的方法

$(fn)   -->  $.fn.ready(fn)  -->$.bindReady()  -->      $.ready(wait)     <--> $.holdReady(hold)

下面这个是init函数的一部分代码,就是判断$里面的参数是函数

1   //处理: $(function)   简写 $(document).ready(function)2   if (jQuery.isFunction(selector)) {3                   return rootjQuery.ready(selector);        ->所以这里你应该明白了为什么可以$(fn) 替代$(document).ready(fn)4   }                        --> rootjQuery=$(document)

那$(document).ready(fn)后又怎么办呢? 难道$(document)不是实例化的一个jQuery对象,它当然又要去调用$.fn.ready的函数

好,来到了$.fn.ready,好吧这个函数并没有管如何处罚dom ready事件,而只是关心callbacks函数队列fn ,意思就是你$(fn1),$(fn2),

它靠得还是全局的readyList,然后这个readyList是一个Deferred对象,知道它的重要了吧!

1  /*$(fn)--> $(document).ready(fn) 为什么是$(document)而不是其他$("body")呢?2 * $(function () {console.log(this === document); }); -->true3 */4   ready: function (fn) {5      //Attach the listeners6          jQuery.bindReady();78       //增加$(fn)里的回调函数 以便domready触发时候   readyList.resolveWith(document,[jQuery]); 这里readyList是全局的变量9        readyList.done(fn);1011       return this;12      },

       --->这里可以看到,继续去调用$.bindReady(),这里不关系dom ready是如何触发的

来到bindReady函数,根据不同的函数支持情况进行了不同的处理,在这里多少能学点浏览器兼容的知识了吧,

其实学了jQuery,神马浏览器兼容知识你都学到了.但是这个函数真正关心得只是事件的添加,不关心事件如何触发,,

这里最终的callback触发还是交给了$.ready  这里会有一个DOMContentLoaded公用的函数

1   /*从这里可以看出来其实$(function(){})如果页面存在很多的话,也不太会影响性能,因为这个$.bindReady只执行一次2 * 而以后$(fn)进来的函数,都通过deferred的done函数添加进来,只要这个对象resolve了,立马后面所有的fn立即执行3 */4   bindReady: function () {5         //如果readyList存在,直接返回,证明这里已经创建了一个deferred对象6           if (readyList) {7                     return;8            }9         //创建jQuery 私有的deferred10          readyList = jQuery._Deferred();11 12        //确保browser event已经触发过后,$(document).ready()也将会被调用13         //这个状态表示Fully loaded,document已经完全加载了14      if (document.readyState === "complete") {       -->jQuery代码总担心出错,但是你不要担心你的回调会因为多处的被添加到事件添加器中去而被多次触发                                               --> $.ready会帮你处理的 ~_~15                     //Handle it asynchronously to allow scripts the opportunity to delay ready16           return setTimeout(jQuery.ready, 1);17        }18 19           //Mozilla, Opera and webkit nightlies currently support this event20           if (document.addEventListener) {21                    //支持DOMContentLoaded事件了,这样就简单了22               document.addEventListener("DOMContentLoaded", DOMContentLoaded, false);23 24             //A fallback to window.onload, that will always work  ->jQuery代码总担心出错,               //但是你不要担心,这样会不会多次触发你的回调函数,告诉你当然不会!25              window.addEventListener("load", jQuery.ready, false);26 27            //If IE event model is used28         } else if (document.attachEvent) {29                 //这里主要担心页面内有iframe,所以使用onreadystatechange触发30                   document.attachEvent("onreadystatechange", DOMContentLoaded);31 32                 //A fallback to window.onload, that will always work33                     window.attachEvent("onload", jQuery.ready);34 35                   //如果是ie并且页面window是toplevel的,继续检查-> ie关心的代码,doScrollCheck()又是神马呢?36                   //MDN: window.frameElement == null if the window is top-level37                   var toplevel = false;38 39                     try {40                         toplevel = window.frameElement == null;41                     } catch (e) { }42 43                     if (document.documentElement.doScroll && toplevel) {44                         doScrollCheck();45                     }46                 }47             },

//原来DOMContentLoaded还是在这里,最后都是交给了$.ready()处理,而DOMContentLoaded并没有做什么,只是又一次的去掉事件监听      if (document.addEventListener) {                                               DOMContentLoaded = function () {                document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false);                jQuery.ready();            };

        } else if (document.attachEvent) {            DOMContentLoaded = function () {                // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).                if (document.readyState === "complete") {                    document.detachEvent("onreadystatechange", DOMContentLoaded);                    jQuery.ready();                }            };        }

 /* 这里只针对ie,当页面DOM未加载完成时,调用doScroll方法时,会产生异常。       * 那么我们反过来用,如果不异常,那么就是页面DOM加载完毕了!  * 这里的想法真的很淫荡!  */        function doScrollCheck() {            if (jQuery.isReady) {                return;            }            try {                // If IE is used, use the trick by Diego Perini                // http://javascript.nwbox.com/IEContentLoaded/                document.documentElement.doScroll("left");            } catch (e) {                setTimeout(doScrollCheck, 1);                return;            }

            //直到没有异常的时候,执行$.ready()            jQuery.ready();        }                                                                                                           -->你最终会发现,其实都是交给了$.ready()处理,不管你怎么触发事件 ^_^

好吧,最后所有的重头戏都落到了ready,最后的callbacks都是靠他触发的,而他里面的readyList又一是一个deferred对象,你懂了吧,他要

resolveWith(document,[jQuery]),你知道这个document意味着什么吗?$(function(){console.log(this===document)}) ~_~.

1  /*$.holdReady 原来jQuery才是真正的hold住哥,这里它要hold domReady事件,2 * $.holdReady(true)--> 延迟hold一次,延迟domReady事件触发3 * $.holdReady(false) --> 释放hold一次,如果释放后$.readyWait=0,则触发domReady事件4 * 整个函数的功能就是延迟domReady事件,比如你需要动态加载一个jQuery插件神马的,然后你又要使用这个插件5 * $.holdReady(true);$.getScript("myplugin.js", function() { $.holdReady(false);});6 ->使用上面这个语句整个场面都hold住了,加载完成后释放7 */8             holdReady: function (hold) {                           -->这里你总算看到了神马是hold住哥9                 if (hold) {10                     jQuery.readyWait++;11                 } else {12                     jQuery.ready(true);13                 }14             },15 /*归根揭底,dom树加载完成都是靠它来触发callbacks,只是不同的浏览器通过不同的方式来触发$.ready()16 */17      ready: function (wait) {18                 //释放hold状态或者dom 事件触发19         if ((wait === true && ! --jQuery.readyWait) || (wait !== true && !jQuery.isReady)) {20             //Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).21               if (!document.body) {22                     return setTimeout(jQuery.ready, 1);23              }24 25           //表面dom树已加载完毕26              jQuery.isReady = true;27 28             //if 一个正常的dom函数事件触发了,但是还有hold的状态,返回把,先不触发29              if (wait !== true && --jQuery.readyWait > 0) {30                      return;31               }32             //触发绑定在 readyList.done(fn);中得函数33             //函数原来还是在这里触发的34            readyList.resolveWith(document, [jQuery]);35 36             //触发任何绑在document ready的事件37            //$(document).bind({"ready": function () {alert("document ready");} });38            if (jQuery.fn.trigger) {39                         jQuery(document).trigger("ready").unbind("ready");40                     }41                 }42             },

这上面有个2B的代码 $(document).bind("ready",function(){..})不知道哪个2B青年会用这个方法...

好吧,如果看懂了上面的代码,你完全可以写一个自己的$(function(){}) 而不必为了jQuery为了符合大众的口味去这样实现!

转载于:https://www.cnblogs.com/nothingbrother/archive/2011/12/05/2277369.html

jQuery deferred应用dom加载完毕详细源码分析(三)相关推荐

  1. 这篇文章绝对让你深刻理解java类的加载以及ClassLoader源码分析

    前言 package com.jvm.classloader;class Father2{public static String strFather="HelloJVM_Father&qu ...

  2. 描述一下JAVA的加载过程_JVM源码分析之Java类的加载过程

    简书 占小狼 转载请注明原创出处,谢谢! 趁着年轻,多学习 背景 最近对Java细节的底层实现比较感兴趣,比如Java类文件是如何加载到虚拟机的,类对象和方法是以什么数据结构存在于虚拟机中?虚方法.实 ...

  3. clamav --reload 加载病毒库源码分析

    基本流程可以参考clamav中clamdscan --version 不生效 我们直接从解析command开始.parse_command函数返回COMMAND_RELOAD类型.然后进入execut ...

  4. 下血本买的!Flutter中网络图片加载和缓存源码分析,看看这篇文章吧!

    目录 想要成为一名优秀的Android开发,你需要一份完备的知识体系,在这里,让我们一起成长为自己所想的那样. PagerAdapter 介绍 ViwePager 缓存策略 ViewPager 布局处 ...

  5. Flutter中网络图片加载和缓存源码分析,踩坑了

    关于Android的近况 大家都知道,今年移动开发不那么火热了,完全没有了前两年Android开发那种火热的势头,如此同时,AI热火朝天,很多言论都说Android不行了.其实不光是Android,i ...

  6. Android开发必会技术!Flutter中网络图片加载和缓存源码分析,完整PDF

    起因 事情是这样的. 4年前毕业那会,呆在公司的短视频项目,做 视频.那会做得比抖音还早,但是由于短视频太烧钱了,项目被公司关掉了.当时需要开发横竖屏直播/异步视频的场景,就研究下了市场上的 app, ...

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

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

  8. 2款不同样式的CSS3 Loading加载动画 附源码

    原文:2款不同样式的CSS3 Loading加载动画 附源码 我们经常看到的Loading加载很多都是转圈圈的那种,今天我们来换一种有创意的CSS3 Loading加载动画,一种是声波形状的动画,另一 ...

  9. 2.2 LayoutInflater 加载布局文件源码

    LayoutInflater 加载布局文件源码 LayoutInflater是一个用于将xml布局文件加载为View或者ViewGroup对象的工具,我们可以称之为布局加载器. 获取LayoutInf ...

最新文章

  1. python列表做参数传值_python不定参数传值怎么做-问答-阿里云开发者社区-阿里云...
  2. linux获取url中文内容_Chrome OS 似乎将在Linux 的方向上更进一步
  3. HDU-3743 Minimum Sum,划分树模板
  4. 软件测试中的α测试、β测试和λ测试
  5. java 压缩技术_Java压缩技术(三) ZIP解压缩——Java原生实现
  6. github提交,却不显示提交记录
  7. 2台服务器负载均衡后synchronized_一篇有趣的负载均衡算法实现
  8. java 贪吃蛇 控制台_控制台游戏贪吃蛇Java版
  9. [Unity2018.2]ShaderGraph更新详解
  10. 自己定制树莓派Linux内核的步骤
  11. 关于微信退款出现错误代码:52的解决方法【转】
  12. 中国能源消费结构(2003-2019年)
  13. ibus五笔快捷键 繁简 单字 词组切换
  14. 二次开发—Ribbon界面
  15. 基于ABAQUS蠕变储层稠油蒸汽吞吐开发过程数值模拟
  16. 《数据库系统概论》3.3.1模式的定义与删除实操
  17. Baklib分享|知识管理是企业发展的风向标
  18. 文章本天成妙手偶得之
  19. Word 2019 自带公式快速编号方法
  20. B数和B+数的区别,Mysql为什么使用B+数据结构

热门文章

  1. 【SSL】错误java.security.UnrecoverableKeyException: Cannot recover key
  2. AWS 基础服务学习
  3. REST API解析
  4. python leetcode_七十五、Python | Leetcode哈希表系列
  5. easyui树拖拽排序java_项目中集成Easyui-Tree,可拖拽更新节点
  6. java 获取进程_java获取指定进程的stat
  7. 小狗扫地机器人与石头_当戴森遇到石头机器人,从容应对 “猫狗拆家”
  8. bootstrap文件不能被识别_树莓派安装openCV做图像识别
  9. mysql pgsql 2017,DB-Engines 2017 年度数据库:PostgreSQL 实至名归
  10. web前端网页设计作业_网页前端设计快速入门技巧