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;
	}

  

转载于:https://www.cnblogs.com/w2154/p/4591797.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值