jQuery源码之ready()事件

          jquery中,等待DOM加载完成再执行的方法ready事件,相信大家经常使用该事件,今天,我们来看下jquery源码中是如何实现该功能的。

一、实例

        首先看下,如何使用ready事件:

$(document).ready(function(){
     console.log(1);
  });

等DOM加载完成后,执行匿名函数,在控制台中打印1。

首先了解一下DOMContentLoaded与window.load()。

DOMContentLoaded是DOM构建完成后触发,window.onload()是等所有的内容加载完成,例如图片等等。DOMContentLoaded事件先触发,后触发window.onload()事件。


二、源码解析:


  1.函数及变量初始化


jQuery.extend({

   isReady: false,   //DOM是否加载完毕,初始化为false

   readyWait: 1,   //需要等待的事件,初始化为1 

	// Hold (or release) the ready event
	holdReady: function( hold ) {  //是否要hold住ready事件。
		
	},

	// Handle when the DOM is ready
	ready: function( wait ) {  //ready函数,执行ready事件是调用

	}
});

/**
 * The ready event handler and self cleanup method
 */
function completed() {   //DOM完成后触发

}

jQuery.ready.promise = function( obj ) {   //ready事件调用的函数
	}


完成工具方法的扩展后,后面代码立即执行了:

2.执行 jQuery.ready.promise()

jQuery.ready.promise();

然我们看下该函数内部代码

jQuery.ready.promise = function( obj ) {
	if ( !readyList ) {     //第一次执行时readylist为undefined,进入if

		readyList = jQuery.Deferred();   //readyList为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" ) {  //如果DOM已经加载完了,我们不再触发complete事件,直接走ready
			// Handle it asynchronously to allow scripts the opportunity to delay ready
			setTimeout( jQuery.ready );

		} else {      

			// Use the handy event callback
			document.addEventListener( "DOMContentLoaded", completed, false );  //给文档添加DOMContentLoaded事件

			// A fallback to window.onload, that will always work
			window.addEventListener( "load", completed, false );   //如果DOMContentLoade不执行,以此为备用,总是执行
		}
	}
	return readyList.promise( obj );  //返回状态不可改的Deferred对象
};


3.执行jquery实例ready事件

当工具方法都初始化完之后,开始执行$(document).ready()中的ready().

jQuery.fn.ready = function( fn ) {
	// Add the callback
	jQuery.ready.promise().done( fn );   //jQuery.ready.promise()函数,由于初始化工具方法时,已经执行过一遍,代码会直接返回Deferred对象。
	return this;                          //把入参添加到done中
};

4.DOM树构造完成

触发complete事件

function completed() {
	document.removeEventListener( "DOMContentLoaded", completed, false ); //去除绑定的函数
	window.removeEventListener( "load", completed, false );
	jQuery.ready();   //执行工具方法的ready
}

5.执行工具方法的ready方法

ready: function( wait ) {

		// Abort if there are pending holds or we're already ready
		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {  //如果等待或者已经等待后了,跳过
			return;
		}

		// Remember that the DOM is ready
		jQuery.isReady = true;

		// If a normal DOM Ready event fired, decrement, and wait if need be
		if ( wait !== true && --jQuery.readyWait > 0 ) {
			return;
		}

		// If there are functions bound, to execute
		readyList.resolveWith( document, [ jQuery ] );   //触发resolveWith执行done中添加的函数

		// Trigger any bound ready events
		if ( jQuery.fn.triggerHandler ) {
			jQuery( document ).triggerHandler( "ready" );
			jQuery( document ).off( "ready" );
		}
	}
});





你可能感兴趣的:(ready,jquery源码)