jquery源码之事件系统-- jQuery.event

每个网站,交互的核心都是事件。浏览器环境一般提供两种事件绑定的方式:

一个是通过dom句柄的使用。如: element.onclick = function() {}

另一种就是事件委托了,如:docuement.addEventListener(element, function() {});

基于第二种,不同浏览器也有不用的api接口。这是需要注意的地方

当然,如果使用jquery,这些东西都不是你要关心的,他会替你解决一切。

jquery事件系统的强大是毋庸置疑的。那我们就来看看他到底强大在哪。

首先jquery事件系统是基于$.data缓存系统的,这个在先前的博文就有提及到。

jquery事件系统功能是非常强大的,所以它的块头也比较大。所以我们不能一口就把它给全吃掉。

我们以一定得顺序来探索jquery时间系统。我们首先看看jquery核心方法jquery.event.add,再由jquery.fn.on这个统一入口逐层分析整个事件系统。

让我们先来看看 jquery的核心绑定事件的方法。

jquery.event.add = function( elem, types, handler, data, selector ) {



		var 

			// 该dom元素的缓存数据

			elemData, 

			// 事件处理函数

			eventHandle, 

			// 该元素对应的事件集合

			events,

			t, tns, type, 

			// 命名空间

			namespaces, 

			// 处理对象

			handleObj,

			handleObjIn, handlers, special;

		

		// 在不支持添加事件的元素上就直接返回

		// Don't attach events to noData or text/comment nodes (allow plain objects tho)

		// 在这一步中 通过jquery._data 获取了该元素对应的数据

		if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {

			return;

		}



		// 调用者可以传递一个自定义数据的对象来替代处理方法

		// Caller can pass in an object of custom data in lieu of the handler

		if ( handler.handler ) {

			handleObjIn = handler;

			handler = handleObjIn.handler;

			selector = handleObjIn.selector;

		}



		// Make sure that the handler has a unique ID, used to find/remove it later

		if ( !handler.guid ) {

			handler.guid = jQuery.guid++;

		}

		// 取出缓存对象中对应event事件的对象集合

		// Init the element's event structure and main handler, if this is the first

		events = elemData.events;

		// 不存在则新建一个{}

		if ( !events ) {

			elemData.events = events = {};

		}

		// 事件处理函数

		eventHandle = elemData.handle;

		// 如果函数不存在 则指定一个函数

		if ( !eventHandle ) {

			elemData.handle = eventHandle = function( e ) {

				// Discard the second event of a jQuery.event.trigger() and

				// when an event is called after a page has unloaded

				return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?

					// 事件调度方法

					// 会根据元素的绑定的一些信息,找到对应缓存中的事件处理方法

					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :

					undefined;

			};

			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events

			eventHandle.elem = elem;

		}



		// Handle multiple events separated by a space

		// 处理以空格隔开的多种事件,

		// jQuery(...).bind("mouseover mouseout", fn);

		types = jQuery.trim( hoverHack(types) ).split( " " );

		for ( t = 0; t < types.length; t++ ) {



			tns = rtypenamespace.exec( types[t] ) || [];

			type = tns[1];

			// 获取命名空间(这个是用来自定义事件的)

			namespaces = ( tns[2] || "" ).split( "." ).sort();



			// 如果事件改变了它的类型,则使用特殊事件处理方法

			// If event changes its type, use the special event handlers for the changed type

			special = jQuery.event.special[ type ] || {};



			// 获取准确的事件类型

			// If selector defined, determine special event api type, otherwise given type

			type = ( selector ? special.delegateType : special.bindType ) || type;



			// 更新special

			// Update special based on newly reset type

			special = jQuery.event.special[ type ] || {};



			// handleObj is passed to all event handlers

			handleObj = jQuery.extend({

				type: type,

				origType: tns[1],

				data: data,

				handler: handler,

				guid: handler.guid,

				selector: selector,

				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),

				namespace: namespaces.join(".")

			}, handleObjIn );



			// 如果未绑定,则把事件绑定在开始获取的事件调度方法上,

			// Init the event handler queue if we're the first

			handlers = events[ type ];

			if ( !handlers ) {

				handlers = events[ type ] = [];

				handlers.delegateCount = 0;



				// Only use addEventListener/attachEvent if the special events handler returns false

				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {

					// Bind the global event handler to the element

					if ( elem.addEventListener ) {

						elem.addEventListener( type, eventHandle, false );



					} else if ( elem.attachEvent ) {

						elem.attachEvent( "on" + type, eventHandle );

					}

				}

			}

			

			if ( special.add ) {

				special.add.call( elem, handleObj );



				if ( !handleObj.handler.guid ) {

					handleObj.handler.guid = handler.guid;

				}

			}



			// 添加事件处理的对象,代理对象插入在队列前面

			// Add to the element's handler list, delegates in front

			if ( selector ) {

				handlers.splice( handlers.delegateCount++, 0, handleObj );

			} else {

				handlers.push( handleObj );

			}



			// Keep track of which events have ever been used, for event optimization

			jQuery.event.global[ type ] = true;

		}



		// Nullify elem to prevent memory leaks in IE

		elem = null;

	}

  

你可能感兴趣的:(jquery)