javascript事件之:jQuery.event.add事件详解

  我们已经了解过jQuery.event下的方法,回顾一下

jQuery.event = {
    global: {},
    add: function( elem, types, handler, data, selector ) {},
    remove: function( elem, types, handler, selector, mappedTypes ) {},
    trigger: function( event, data, elem, onlyHandlers ) {},
    dispatch: function( event ) {},
    handlers: function( event, handlers ) {},
    props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
    fixHooks: {},
    keyHooks: {
        props: "char charCode key keyCode".split(" "),
        filter: function( event, original ) {}
    },
    mouseHooks: {
        props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
        filter: function( event, original ) {}
    },
    fix: function( event ) {},
    special: {
        load: {
            noBubble: true
        },
        focus: {
            // Fire native event if possible so blur/focus sequence is correct
            trigger: function() {},
            delegateType: "focusin"
        },
        blur: {
            trigger: function() {},
            delegateType: "focusout"
        },
        click: {
            trigger: function() {},
            _default: function( event ) {
                return jQuery.nodeName( event.target, "a" );
            }
        },
        beforeunload: {
            postDispatch: function( event ) {}
        }
    },
    simulate: function( type, elem, event, bubble ) {}
}

今天,我们先来了解jQuery.event.add方法

我们先来看源码

/*
  elem: 操作的元素
  types: 事件类型
  handle: 事件触发的方法
  data: 事件触发的方法需要的参数
  selector: 委托的元素
  
  调用: 比如我们在jquery.fn.on中的调用
  jQuery.fn.extend({
    on: function(){
      ...
      jQuery.event.add( this, types, fn, data, selector );
      ...
    }
  })
*/
add: function( elem, types, handler, data, selector ) { var handleObjIn, eventHandle, tmp, events, t, handleObj, special, handlers, type, namespaces, origType,
     /*
     获取绑定在elem上的data缓存 
     */ elemData
= data_priv.get( elem );    //不允许出现文本节或者注释节点。但允许出现空对象{}
if ( !elemData ) { return; }
   //这里的handler允许是对象代替handler函数,这里的对象指的是下面的handlerObj。要我说这里有点累赘。干嘛要非得支持这种写法的多样性,增加阅读复杂度。
  if ( handler.handler ) { handleObjIn = handler; handler = handleObjIn.handler; selector = handleObjIn.selector; }
  //给handler添加一个guid属性,确保handler函数有唯一ID,之后的查找或者删除可以使用它 if ( !handler.guid ) { handler.guid = jQuery.guid++; } // elemData如果没有events属性,给它加上。第一次才会用上
if ( !(events = elemData.events) ) { events = elemData.events = {}; }
  // elemData没有handle属性,给它加上
if ( !(eventHandle = elemData.handle) ) { eventHandle = elemData.handle = 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 !== core_strundefined && (!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; } // 处理用空格分开的多事件操作 types = ( types || "" ).match( core_rnotwhite ) || [""]; t = types.length; while ( t-- ) {
     //typenamespace = /^([^.]*)(?:.(.+)|)$/; tmp
= rtypenamespace.exec( types[t] ) || []; type = origType = tmp[1]; namespaces = ( tmp[2] || "" ).split( "." ).sort(); // There *must* be a type, no attaching namespace-only handlers if ( !type ) { continue; } // 得到特殊处理的事件类型 special = jQuery.event.special[ type ] || {}; // 如果selector有定义,type可能不一样 type = ( selector ? special.delegateType : special.bindType ) || type; // 修正special special = jQuery.event.special[ type ] || {}; // 得到handleObj handleObj = jQuery.extend({ type: type, origType: origType, data: data, handler: handler, guid: handler.guid, selector: selector, needsContext: selector && jQuery.expr.match.needsContext.test( selector ), namespace: namespaces.join(".") }, handleObjIn ); // 初始化elemData.events[type] if ( !(handlers = events[ type ]) ) { handlers = events[ type ] = []; handlers.delegateCount = 0; // 在没有special.setup或者special.setup返回false时候,对元素绑定事件 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle, false ); } } }     //如果有special.add,执行special.add if ( special.add ) { special.add.call( elem, handleObj );        //如果handleObj.handler.guid不存在,吧handler.grid赋值给handleObj.handler.guid if ( !handleObj.handler.guid ) { handleObj.handler.guid = handler.guid; } } // 把handleObj附加到events[type]数组。对于委托事件,delegateCount++并且添加到数组最前面。否则加到数组后面 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; } // 让elem为空,避免ie内存泄露 elem = null; }

上面我们已经对jQuery.event.add的源码做出相应解释。我们再总结一下

这个方法的作用就是对elem身上的data缓存数据进行添加或者修正。之后的大部分操作都是集中在这个数据缓存elemData上操作。

原文地址:https://www.cnblogs.com/pfzeng/p/4188496.html