jQuery事件之:jQuery.event.trigger

  现在我们来看看事件机制中的主动触发,我们要分析的是jQuery.event.trigger。

  先来看看它在jQ源码中的调用。

 // 1, 在jQuery.event.simulate中
 jQuery.event.simulate = function(){
    ...
    if ( bubble ) {
        jQuery.event.trigger( e, null, elem );
    }
    ...
 }
// 2, 事件的实例方法中
 jQuery.fn.extend({
    trigger: function( type, data ) {
        return this.each(function() {
            jQuery.event.trigger( type, data, this );
        });
    },
    triggerHandler: function( type, data ) {
        var elem = this[0];
        if ( elem ) {
            return jQuery.event.trigger( type, data, elem, true );
        }
    }
 })
// 3, ajax中也有主动触发
 jQuery.event.trigger("ajaxStart");
 jQuery.event.trigger("ajaxStop");
 

  看到其调用,我们能猜出其参数,有4个。

  来看源码:

/*
type: 事件的类型
data: 事件传递的参数
elem: 绑定事件的元素
onlyHandler: 是否冒泡和触发默认事件
*/
trigger: function( event, data, elem, onlyHandlers ) {
    var i, cur, tmp, bubbleType, ontype, handle, special,
        eventPath = [ elem || document ],
        //event支持对象的写法, 比如{"type": "click"}
        type = core_hasOwn.call( event, "type" ) ? event.type : event,
        namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];

    cur = tmp = elem = elem || document;

    // 如果是文本节点和注释节点,return;
    if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
        return;
    }

    // focus/blur morphs to focusin/out; ensure we‘re not firing them right now
    if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
        return;
    }
    //如果有命名空间,重新得到type和namepaces
    if ( type.indexOf(".") >= 0 ) {
        // Namespaced trigger; create a regexp to match event type in handle()
        namespaces = type.split(".");
        type = namespaces.shift();
        namespaces.sort();
    }
    // 得到ontype。&&的 用法, 如果type不含有‘:‘, 比如type=‘click‘, ontype = ‘onclick‘, 否则ontype = false
    ontype = type.indexOf(":") < 0 && "on" + type;

    // 构建或得到event对象
    event = event[ jQuery.expando ] ?
        event :
        new jQuery.Event( type, typeof event === "object" && event );

    // 以下都是构建event实例方法
    event.isTrigger = onlyHandlers ? 2 : 3;
    event.namespace = namespaces.join(".");
    event.namespace_re = event.namespace ?
        new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
        null;
    event.result = undefined;
    if ( !event.target ) {
        event.target = elem;
    }

    // 初始化data
    data = data == null ?
        [ event ] :
        jQuery.makeArray( data, [ event ] );

    // Allow special events to draw outside the lines
    special = jQuery.event.special[ type ] || {};
    if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
        return;
    }

    // Determine event propagation path in advance, per W3C events spec (#9951)
    // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
    // 得到冒泡的路径eventPath, 如,[div, h3, body, html, Document]
    if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {

        bubbleType = special.delegateType || type;
        if ( !rfocusMorph.test( bubbleType + type ) ) {
            cur = cur.parentNode;
        }
        for ( ; cur; cur = cur.parentNode ) {
            eventPath.push( cur );
            tmp = cur;
        }

        // Only add window if we got to document (e.g., not plain obj or detached DOM)
        if ( tmp === (elem.ownerDocument || document) ) {
            eventPath.push( tmp.defaultView || tmp.parentWindow || window );
        }
    }

    // Fire handlers on the event path
    i = 0;
    while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {

        event.type = i > 1 ?
            bubbleType :
            special.bindType || type;

        //得到父元素的handle
        handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
        // 存在则执行handle
        if ( handle ) {
            handle.apply( cur, data );
        }

        // 调用的是元素绑定的时间
        handle = ontype && cur[ ontype ];
        if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
            event.preventDefault();
        }
    }
    event.type = type;
    
    // If nobody prevented the default action, do it now
    if ( !onlyHandlers && !event.isDefaultPrevented() ) {

        if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
            jQuery.acceptData( elem ) ) {
            if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {

                // 得到行内绑定的方法
                tmp = elem[ ontype ];
                //对行内绑定到的方法制空
                if ( tmp ) {
                    elem[ ontype ] = null;
                }

                // 执行
                jQuery.event.triggered = type;
                elem[ type ]();
                jQuery.event.triggered = undefined;
                //重新绑定回去
                if ( tmp ) {
                    elem[ ontype ] = tmp;
                }
            }
        }
    }
    return event.result;
},

主要流程就是取得data缓存数据,根据是否冒泡去执行相应的方法。

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。