jQuery之ready源码分析
只要使用过jQuery的,想必对ready都不陌生,$(function(){})和$(document).ready(function(){})的使用更是习以为常。
要说到window.onload与document.ready的区别也能谈出个一二,最重要的区别就是:
window.onload是在dom文档树以及所有文件都加载完成后,才执行;
而document.ready是,只要dom文档树加载完,就执行,且当dom文档树加载完就执行的好处就是,当页面中的图片等外部资源过多时,window.onload迟迟不能触发,这时若还没有绑定事件,用户点击按钮时没有反应,这不影响用户体验么。
咦,Jquery的ready这么牛逼,那Jquery是怎么实现ready这个函数的呢?我们不妨一起来探究探究。
以下Jquery.ready的源码,截自于jQuery 1.12.0。
jQuery.ready.promise = function( obj ) {
if ( !readyList ) {
readyList = jQuery.Deferred();
// Catch cases where $(document).ready() is called
// after the browser event has already occurred.
// we once tried to use readyState "interactive" here,
// but it caused issues like the one
// discovered by ChrisS here:
// http://bugs.jquery.com/ticket/12282#comment:15
if ( document.readyState === "complete" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
window.setTimeout( jQuery.ready );
// Standards-based browsers support DOMContentLoaded
} else if ( document.addEventListener ) {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", completed );
// A fallback to window.onload, that will always work
window.addEventListener( "load", completed );
// If IE event model is used
} else {
// Ensure firing before onload, maybe late but safe also for iframes
document.attachEvent( "onreadystatechange", completed );
// A fallback to window.onload, that will always work
window.attachEvent( "onload", completed );
// If IE and not a frame
// continually check to see if the document is ready
var top = false;
try {
top = window.frameElement == null && document.documentElement;
} catch ( e ) {}
if ( top && top.doScroll ) {
( function doScrollCheck() {
if ( !jQuery.isReady ) {
try {
// Use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
top.doScroll( "left" );
} catch ( e ) {
return window.setTimeout( doScrollCheck, 50 );
}
// detach all dom ready events
detach();
// and execute any waiting functions
jQuery.ready();
}
} )();
}
}
}
return readyList.promise( obj );
};
从上面的源码中,可以看出,jQuery.ready主要通过以下几个东东来判断dom文档树是否加载完成:
(1) document.readyState
(2) DOMContentLoaded
(3) onreadystatechange
(4) doScroll
下面,我们就一步一步来解析
1、 document.readyState
readyState是个什么东东呢?它是document的一个属性值,返回当前文档的状态,该属性会根据文档加载情况,返回如下几个属性值:
|
属性值 |
意义 |
|
uninitialized |
还未开始载入 |
|
loading |
载入中 |
|
interactive |
已加载,文档与用户可以开始交互 |
|
complete |
载入完成 |
从属性值,可得知,倘若当我们判断document.readyState为complete,那么DOM文档树就是加载完毕。但,从上面源码注释(6--11行)中可以得知ChrisS发现了一个很特别的问题,所以我们在判断document.readyState === ‘complete’后,执行jQuery.ready,需要延迟一下。但上面的代码中,怎么没有延迟时间呢?
那是因为倘若我们没有设置延迟时间,setTimeout就会根据当前浏览器及操作系统,自动给它设定一个最小延迟时间。在《JavaScript忍者的秘密》中曾提到:

2、 DOMContentLoaded事件
从上面的源代码注释中,可以看出DOMContentLoaded是基于标准的浏览器的。
那么它的作用是什么呢?
当DOM文档树加载完成后,即触发。
所以可以在标准的浏览器中判断DOMContentLoaded,来判断DOM树,是否加载完成。
3、 onreadystatechange事件
上面的DOMContentLoaded事件是基于标准的浏览器的,那倘若不标准的呢,如IE,则使用onreadystatechange事件。
咦,怎么感觉如此熟悉。
XMLHttpRequest—>Ajax。想起来了么。在IE中onreadystatechange是私有化的,即所有元素都存在onreadystatechange事件,而W3C标准中,仅XMLHttpRequest对象中存在onreadystatechange事件。所以当事件触发时,倘若onreadystatechange === complete,则可视为DOM树加载完成。
4、 doScroll
从上面的源码中的注释(49--50行),可得,Diego Perini报告一种检测IE下DOM文档是否加载完成的方法,即,使用doScroll。
咦,上面onreadystatechange事件,不是能处理了吗?!!
是的,但是它有个弊端,就是当页面中存在图片时,可能反而会晚于onload事件后,触发。
为什么呢?
因为我们是依据onreadystatechange === complete来判断的嘛,如果图片没加载或者正在加载中,那么onreadystatechange就不等于complete了哦。
所以为了保险起见,再用doScroll来检测。
doScroll的原理就是,当页面DOM未加载完成时,调用doScroll方法,会产生异常。所以利用try-catch来对doScroll捕获异常就可以判断DOM文档是否加载完咯。
好了,jQuery.ready的源码就解析到这儿,纯属自己观点,有什么不对,请狠狠拍砖且交流,谢谢。
jQuery之ready源码分析的更多相关文章
- Jquery之isPlainObject源码分析
今天对Jquery中 isPlainObject 源码分析. 1. isPlainObject 方法的作用: 用来判断传入参数,是否是对象. 2. 源码分析:isPlainObject: funct ...
- jQuery.clean()方法源码分析(一)
在jQuery 1.7.1中调用jQuery.clean()方法的地方有三处,第一次就是在我之前的随笔分析jQuery.buildFramgment()方法里面的,其实还是构造函数的一部分,在处理诸如 ...
- jQuery实现jsonp源码分析(京东2015面试)
// Bind script tag hack transportjQuery.ajaxTransport( "script", function(s) { // This tra ...
- jQuery 2.0.3 源码分析 事件绑定 - bind/live/delegate/on
事件(Event)是JavaScript应用跳动的心脏,通过使用JavaScript ,你可以监听特定事件的发生,并规定让某些事件发生以对这些事件做出响应 事件的基础就不重复讲解了,本来是定位源码分析 ...
- jQuery1.9.1源码分析--数据缓存Data模块
jQuery1.9.1源码分析--数据缓存Data模块 阅读目录 jQuery API中Data的基本使用方法介绍 jQuery.acceptData(elem)源码分析 jQuery.data(el ...
- jQuery 源码分析(十八) ready事件详解
ready事件是当DOM文档树加载完成后执行一个函数(不包含图片,css等),因此它的触发要早于load事件.用法: $(document).ready(fun) ;fun是一个函数,这样当DOM树加 ...
- jQuery实现DOM加载方法源码分析
传统的判断dom加载的方法 使用 dom0级 onload事件来进行触发所有浏览器都支持在最初是很流行的写法 我们都熟悉这种写法: window.onload=function(){ ... } 但 ...
- jQuery-1.9.1源码分析系列(二)jQuery选择器
1.选择器结构 jQuery的选择器根据源码可以分为几块 init: function( selector, context, rootjQuery ) { ... // HANDLE: $(&quo ...
- angular源码分析:angular中jqLite的实现——你可以丢掉jQuery了
一.从function JQLite(element)函数开始. function JQLite(element) { if (element instanceof JQLite) { //情况1 r ...
随机推荐
- bootstrap之clearfix
bootstrap之clearfix 在bootstrap辅助类中有那么一类,是这么定义的: 利用clearfix样式清除浮动,但是前提条件是在超小型屏幕上能显示才行(因为其是用visible-xs样 ...
- 服务器使用FTP命令行 无法传送文件 卡在150 Opening data channel for file transfer
猜测,是因FTP服务器采用了主动模式,在创建数据传输通道时,服务器会以一个随机的端口,连接回来. 临时解决方案: 因不知道请求回来使用的哪个段的端口,因此,暂时关闭了防火墙.即能正常传输文件了.
- 温故而知新 css + html 超级牛逼的居中策略
该方法甚至可以解决img内容居中的问题 套路:最外层div宽度为居中内容所占的宽度(通常是1170px),并且使其居中(margin:auto) 里层的div宽度为全屏(通常是1920px;)再mar ...
- VIM配置
Linux下的编辑器以vim和emacs为主流,一个编辑器之神,一个是神的编辑器. 本文以主要介绍如何在linux下以vim为基础搭建一个比较顺手的代码编辑器. 有两种比较流行的方式: 自动安装 手动 ...
- Jquery 仿 android Toast效果
JS代码如下: /** * 模仿android里面的Toast效果,主要是用于在不打断程序正常执行的情况下显示提示数据 * @param config * @return */var Toast = ...
- 看看Maple T.A.的详细作用
Maple T.A.是一个基于互联网的在线考试和智能评分系统,是Maplesoft公司 与美国数学协会(MAA)合作开发的成果,在全球拥有大量的院校用户.Maple T.A.提供了用户数据库.所见即所 ...
- 小知识 安卓线程和ui
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- nodejs事件轮询详述
目录 概述 nodejs特点 事件轮询 关于异步方法 概述 关于nodejs的介绍网上资料非常多,最近由于在整理一些函数式编程的资料时,多次遇到nodejs有关的内容.所以就打算专门写一篇文章总结一下 ...
- 大白话讲解Promise(一)
去年6月份, ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被列为正式规范.作为ES6中最重要的特性之一,我们有必要掌握并理解透彻.本文将由浅到深,讲解Promise的基本 ...
- 在Visual Studio上开发Node.js程序
[题外话] 最近准备用Node.js做些东西,于是找找看能否有Visual Studio上的插件以方便开发.结果还真找到了一个,来自微软的Node.js Tools for Visual Studio ...