jQuery事件之:jQuery.event.trigger

  如今咱們來看看事件機制中的主動觸發,咱們要分析的是jQuery.event.trigger。html

  先來看看它在jQ源碼中的調用。node

 // 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個。ajax

  來看源碼:緩存

/*
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緩存數據,根據是否冒泡去執行相應的方法。app

相關文章
相關標籤/搜索