Posted in Javascript onJuly 31, 2011
.remove 所作的事情与上一篇提到的.add 刚好相反。且与.add中的处理代码一一对应,即 .add 中有多少种添加事件的方式.remove就有对应的删除方式。
.remove 定义了四个参数 elem, types, handler, pos 。从字面上看四个参数的意义很明了
elem 为HTMLElement
types 为String类型,事件名称如'click'或'mouseover mouseout'
handler 为Function类型,事件回调函数
pos 为Number类型,指定数组位置
但.remove内部没这么简单,如
1,handler 有时会传布尔类型false,这时会把handler赋值为另一个函数(此处的处理同.add)。
if ( handler === false ) { handler = returnFalse; }
2, types 有时会为一个对象,这时真正的handler是types.handler,types是types.type。
// types is actually an event object here if ( types && types.type ) { handler = types.handler; types = types.type; }
我们知道变量命名要具有意义,名副其实而避免误导。从这个意义上讲,jQuery中存在大量这样的写法,一个变量往往具有多种含义,晦涩难读。如这里的types,应该是String类型,但实际内部对typeos为Object类型也做了处理。这是JS没有类型检查的原因导致。反过来讲这种语言会比较灵活,jQuery才如此 紧凑,内聚。
闲言少叙,看看.remove方法都做了哪些事。
1、当只传elem时,会将elem上添加的所有事件都删除。如$('#id').unbind()
2、当types为String,且以点号(.)开头时将删除该命名空间下的事件。如$('#id').unbind('.name')。会把添加click.name,mouseover.name等都删除。
对应的代码如下
// Unbind all events for the element if ( !types || typeof types === "string" && types.charAt(0) === "." ) { types = types || ""; for ( type in events ) { jQuery.event.remove( elem, type + types ); } return; }
我们发现for in中是个递归调用。
如果这么调用
jQuery.event.remove(el, 'click', fn)
那么是不会走上面的递归的,而是直接进入了while循环
while ( (type = types[ i++ ]) ) { ... }
这是标准的删除事件的流程。大概步骤如下
1、判断事件名称是否具有命名空间(以点号区分),如果没有命名空间则删除该事件名称下的所有事件。否则只删除命名空间的某事件。
2、取得事件数组(eventType = events[ type ]),如果没有传handler则表示删除该类型事件的所有hanlder,否则只删除该事件类型的指定handler。
3、对特殊事件(如live)的处理
4、最后对elemData进行处理,如果events为空对象则删除elemData的events和handle属性。如
// Remove the expando if it's no longer used if ( jQuery.isEmptyObject( events ) ) { var handle = elemData.handle; if ( handle ) { handle.elem = null; } delete elemData.events; delete elemData.handle; if ( jQuery.isEmptyObject( elemData ) ) { jQuery.removeData( elem, undefined, true ); } }
jQuery事件管理数据结构图:
读jQuery之十二 删除事件核心方法
声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@