jQuery 1.9.1源码分析系列(十)事件系统之绑定事件

2020-05-29 07:15:45易采站长站整理

  if ( types && types.preventDefault && types.handleObj ) {
// ( event ) dispatched jQuery.Event
handleObj = types.handleObj;
//types.delegateTarget是事件托管对象
jQuery( types.delegateTarget ).off(
//组合jQuery识别的type
handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
handleObj.selector,
handleObj.handler
);
return this;
  }
  if ( typeof types === "object" ) {
// ( types-object [, selector] )
for ( type in types ) {
this.off( type, selector, types[ type ] );
}
return this;
  }
  if ( selector === false || typeof selector === "function" ) {
// ( types [, fn] )
fn = selector;
selector = undefined;
  }
  if ( fn === false ) {
fn = returnFalse;
  }
  return this.each(function() {
jQuery.event.remove( this, types, fn, selector );
  });
}

  接下来分析一下事件解绑的低级api jQuery.event.remove。

jQuery.event.remove

  jQuery使用.off()函数伤处绑定的事件时内部调用的基础函数是jQuery.event.remove。该函数的处理流程如下

  1. 分解传入的要删除的事件类型types,遍历类型,如果要删除的事件没有事件名,只有命名空间则表示删除该命名空间下所有绑定事件


//分解types为type.namespace为单位元素的数组
types = ( types || "" ).match( core_rnotwhite ) || [""];
t = types.length;
while ( t-- ) {
tmp = rtypenamespace.exec( types[t] ) || [];
type = origType = tmp[1];
namespaces = ( tmp[2] || "" ).split( "." ).sort();

//解绑当前元素的当前命名空间(types[ t ])上所有的事件
if ( !type ) {
for ( type in events ) {
jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
}
continue;
}
...

  2. 遍历类型过程中,删除匹配的事件,代理计数修正


type = ( selector ? special.delegateType : special.bindType ) || type;
handlers = events[ type ] || [];
tmp = tmp[2] && new RegExp( "(^|.)" + namespaces.join(".(?:.*.|)") + "(.|$)" );
//删除匹配事件
origCount = j = handlers.length;
while ( j-- ) {
handleObj = handlers[ j ];

//各种满足移除事件的条件才能移除
if ( ( mappedTypes || origType === handleObj.origType ) &&
( !handler || handler.guid === handleObj.guid ) &&
( !tmp || tmp.test( handleObj.namespace ) ) &&
( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
handlers.splice( j, 1 );
        if ( handleObj.selector ) {