jQuery源码学习(版本1.11)-ready

来源:互联网 发布:网络用语 夯是什么意思 编辑:程序博客网 时间:2024/06/06 07:21

概述

本文详细分析了jquery-1.11.1.js源码文件行数:3394~3537;
代码简介:
定义了jQuery.fn.ready,本质是使用Deferred实现的一个执行异步回调函数的机制,在dom加载完毕之后,执行绑定的回调函数;
下文是代码的详细分析。

代码分析

// Deferred对象var readyList;// JQ对象的ready方法// 后续代码可以发现,其实无论哪个JQ对象去执行ready方法,实际效果都是一样的,从这里也可以看出上下文没有应用在jQuery.ready里面// 实际ready方法只有一个readyList,也只使用一个DeferredjQuery.fn.ready = function( fn ) {// 实际执行就是将传入的fn添加到readyList中jQuery.ready.promise().done( fn );return this;};// 扩展工具变量及函数jQuery.extend({// 用于判断dom节点是否已经加载完毕isReady: false,// 计数变量,每执行一次holdReady都会加1readyWait: 1,// hold不为空则增加readyWait,否则触发一次readyholdReady: function( hold ) {if ( hold ) {jQuery.readyWait++;} else {jQuery.ready( true );}},// 定义工具方法ready// 当JQ对象调ready方法时,会执行jQuery.ready.promise,该方法里面实际就是执行本ready方法ready: function( wait ) {// 如果--jQuery.readyWait不为0则返回,表示还需要等待,需要继续触发readyif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {return;}// 异步递归兼容某些bug防止document.body没加载完if ( !document.body ) {return setTimeout( jQuery.ready );}// 设置isReady为truejQuery.isReady = true;// --jQuery.readyWait > 0则必须继续等待,需要继续触发readyif ( wait !== true && --jQuery.readyWait > 0 ) {return;}// 执行readyList里的回调readyList.resolveWith( document, [ jQuery ] );// 触发ready函数执行绑定的其他回调if ( jQuery.fn.triggerHandler ) {jQuery( document ).triggerHandler( "ready" );jQuery( document ).off( "ready" );}}});/** * 去除事件监听 */function detach() {if ( document.addEventListener ) {document.removeEventListener( "DOMContentLoaded", completed, false );window.removeEventListener( "load", completed, false );} else {document.detachEvent( "onreadystatechange", completed );window.detachEvent( "onload", completed );}}/** * ready事件回调函数 */function completed() {// IE也支持document.readyState// 这里使用event.type我感到不解,函数没有形参,应该使用arguments去获取事件,这感觉像是代码缺陷if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {// 因为注册了两个监听器,因此先调用detach去除事件监听,以免多次执行回调detach();// 执行工具函数readyjQuery.ready();}}定义jQuery.ready.promise函数,当JQ对象调用ready函数时,实际就是执行这个函数jQuery.ready.promise = function( obj ) {// 判断readyList是否为空,没有则进入if ( !readyList ) {// 初始化readyListreadyList = jQuery.Deferred();// 使用document.readyState的值判断是否可触发延迟回调if ( document.readyState === "complete" ) {// 使用setTimeout制造异步,保证jQuery.ready在当前一段js代码跑完后再执行setTimeout( jQuery.ready );// document.readyState值不为"complete",则监听事件,} else if ( document.addEventListener ) {// 监听DOMContentLoaded事件document.addEventListener( "DOMContentLoaded", completed, false );// 同时监听load事件,是为了保证JQ对象调用ready时,实际页面已经处于完全加载的状态// 某些浏览器onload有可能优先执行,就没有执行DOMContentLoaded了window.addEventListener( "load", completed, false );// 兼容IE} else {document.attachEvent( "onreadystatechange", completed );window.attachEvent( "onload", completed );// If IE and not a frame// continually check to see if the document is readyvar 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 setTimeout( doScrollCheck, 50 );}// detach all dom ready eventsdetach();// and execute any waiting functionsjQuery.ready();}})();}}}// 返回Deferred里的promise对象return readyList.promise( obj );};


0 0
原创粉丝点击