jQuery源码分析之jQuery.event.remove方法

方法的源码分析如下:

remove: function( elem, types, handler, selector, mappedTypes ) {
		var j, handleObj, tmp,
			origCount, t, events,
			special, handlers, type,
			namespaces, origType,
			//获取该元素的jQuery内部数据
			elemData = jQuery.hasData( elem ) && jQuery._data( elem );
        //如果内部数据不存在,或者内部数据没有events域那么直接返回!
		if ( !elemData || !(events = elemData.events) ) {
			return;
		}
        //可以传入一个通过空格分隔的事件类型
		// Once for each type.namespace in types; type may be omitted
		types = ( types || "" ).match( rnotwhite ) || [ "" ];
		t = types.length;
		//对所有的事件类型进行遍历
		while ( t-- ) {
			//rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
			//如打印[click.test,click,test]
			tmp = rtypenamespace.exec( types[t] ) || [];
			type = origType = tmp[1];
			namespaces = ( tmp[2] || "" ).split( "." ).sort();
            //如果teypes不存在,那么移除所有的事件!也就是当前元素的events域中间的所有的数据!
			// Unbind all events (on this namespace, if provided) for the element
			if ( !type ) {
				//type是空,那么直接移除events下面所有的事件!
				for ( type in events ) {
					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
				}
				continue;
			}
            //获取该类型事件的special进行特殊处理
			special = jQuery.event.special[ type ] || {};
			//如果存在selector那么就是代理对象,否则就是绑定事件到elem上面!
			type = ( selector ? special.delegateType : special.bindType ) || type;
			//获取回调函数集合
			handlers = events[ type ] || [];
			//创建该命名空间下的一个正则表达式
			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
			// Remove matching events
			origCount = j = handlers.length;
			while ( j-- ) {
				//获取该类型事件的所有的handleObj事件
				handleObj = handlers[ j ];
 //判断该对象的origType,如果和handleObj一样表示该类事件全部要移除!但是必须移除的对象是origType,guid,namespace,selector都相同才可以!
				if ( ( mappedTypes || origType === handleObj.origType ) &&
					( !handler || handler.guid === handleObj.guid ) &&
					( !tmp || tmp.test( handleObj.namespace ) ) &&
					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
		//splice接受两个参数,第一个参数表示开始的位置,第二个表示删除的个数!
					handlers.splice( j, 1 );
                  //如果是selector存在表示代理对象,那么把delegateCount递减!
					if ( handleObj.selector ) {
						handlers.delegateCount--;
					}
					//如果special有remove方法,那么直接调用special的remove方法!
					if ( special.remove ) {
						special.remove.call( elem, handleObj );
					}
				}
			}
			// Remove generic event handler if we removed something and no more handlers exist
			// (avoids potential for endless recursion during removal of special event handlers)
			//如果当前事件的回调函数集合已经为空,同时该speical没有tearDown或者tearDown是false,那么用removeEvent方法!
			if ( origCount && !handlers.length ) {
				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
					jQuery.removeEvent( elem, type, elemData.handle );
				}
               //移除当前回调函数集合!
				delete events[ type ];
			}
		}
        //如果events对象已经是空了,那么直接连handle也移除,因为events不存在那么handle已经没有存在的意义了!
		//所以移除handle同时连events域也同时移除!
		// Remove the expando if it's no longer used
		if ( jQuery.isEmptyObject( events ) ) {
			delete elemData.handle;

			// removeData also checks for emptiness and clears the expando if empty
			// so use it instead of delete
			jQuery._removeData( elem, "events" );
		}
	}

如果传入的off("")是空字符串,那么会把所有的事件都移除,见下例:

$("#input").on("click",function(){alert("invoke1")});
$("#input").on("mouseover",function(){alert("invoke2")});
$("#input").off("");//所有的事件都会被移除!

remove方法逻辑:

(1)获取Element上所有的内部数据

(2)获取要移除的types事件类型集合,并且循环移除某一类事件如click=types[i]

(3)如果传入的参数types[i]不存在事件类型,那么移除events域下面的所有的事件。但是如果传入remove("test")时候types[i]也是存在的,只有remove("")才是移除所有的事件

(4)如果传入的types[i]事件类型存在,那么获取events域中该类事件所有的函数句柄,并移出handles相对回调函数,并且把delegate自减!

注意:要移除相应的事件必须是origType,namespace,guid,selector都相等才可以!mappedTypes用于当用户没有传入要移除的事件类型的时候如传入空字符串时候用!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值