• 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上操作。

  • 相关阅读:
    冲刺第七,八天(5月27,28日)
    作业4 阅读《构建之法》 第5.5 第6 第7章
    用户模拟+spec
    第二阶段
    第一次Spring总结
    小组互评和自评
    SPRINT四则运算(第二天)
    开始第一段SPRINT
    四则运算APP
    四则运算 测试与封装 (完善) 5.2 5.3
  • 原文地址:https://www.cnblogs.com/pfzeng/p/4188496.html
Copyright © 2020-2023  润新知