프런트엔드 이벤트 시스템(4)

6387 단어

이벤트 디스패치


먼저 jQuery를 봅시다.이벤트 디스패치 방법
dispatch: function( event ) {

    //  event 
    event = jQuery.event.fix( event );

    var i, j, ret, matched, handleObj,
        handlerQueue = [],
        args = slice.call( arguments ),
        //  
        handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],
        special = jQuery.event.special[ event.type ] || {};

    //  jQuery 
    args[0] = event;
    //  delegate , 
    event.delegateTarget = this;

    if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
        return;
    }

    //  
    handlerQueue = jQuery.event.handlers.call( this, event, handlers );

    //  
    i = 0;
    while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
        event.currentTarget = matched.elem;

        j = 0;
        while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {

            // Triggered event must either 1) have no namespace, or 2) have namespace(s)
            // a subset or equal to those in the bound event (both can have no namespace).
            if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {

                event.handleObj = handleObj;
                event.data = handleObj.data;

                ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
                    .apply( matched.elem, args );

                if ( ret !== undefined ) {
                    if ( (event.result = ret) === false ) {
                        event.preventDefault();
                        event.stopPropagation();
                    }
                }
            }
        }
    }

    // Call the postDispatch hook for the mapped type
    if ( special.postDispatch ) {
        special.postDispatch.call( this, event );
    }

    return event.result;
},

전체 코드를 통독하고 귀납해 보세요, jQuery.event.디스패치는 몇 가지 처리를 해봤어요.
  • 이벤트 대상을 복구
  • 읽기 이벤트 핸들
  • 이벤트 대기열을 가져오고 처리
  • 첫 번째부터 볼게요.
    이벤트 대상에 대한 복구는 이 단계에서 이벤트 대상을 얻어 jQuery의 이벤트 대상이지 원생의 대상이 아니다.여기 jQuery는 읽기만 하던 대상을 읽을 수 있고 쓸 수 있는 대상으로 바꾸어서 마음대로 조작할 수 있습니다.하지만 이벤트 대상 복구에 대해서는 다음 장에서 이벤트 복구와 함께 설명을 드리려고 합니다. 따라서 여기는 되돌아오는 jQuery의 이벤트 대상이라는 것만 알면 됩니다.
    두 번째는 더 이상 말하지 않고 이벤트의 캐시를 읽었다
    그러면 세 번째 지점에 오는 것도 사건 분배의 또 다른 중점이다
    이벤트 대기열의 수령과 처리.
    이전 버전의 jQuery에서 대기열의 생성과 처리는 디스패치에 놓여 있었지만, 지금은 대기열이 jQuery에 맡겨졌습니다.event.handlers를 생성하고 되돌려줍니다. 우선 handlerQueue가 도대체 무엇인지, 즉 jQuery에 대해 살펴보겠습니다.event.handlers로 읽으세요.

    jQuery.event.handlers

    handlers: function( event, handlers ) {
        var i, matches, sel, handleObj,
            handlerQueue = [],
            delegateCount = handlers.delegateCount,
            cur = event.target;
    
        //  、 
        if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
    
            //  , 
            for ( ; cur !== this; cur = cur.parentNode || this ) {
    
                // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
                //  disabled click 
                if ( cur.disabled !== true || event.type !== "click" ) {
                    //  
                    matches = [];
                    for ( i = 0; i < delegateCount; i++ ) {
                        handleObj = handlers[ i ];
    
                        //  selector
                        sel = handleObj.selector + " ";
    
                        if ( matches[ sel ] === undefined ) {
                            //  
                            matches[ sel ] = handleObj.needsContext ?
                            jQuery( sel, this ).index( cur ) >= 0 :
                                jQuery.find( sel, this, null, [ cur ] ).length;
                        }
                        if ( matches[ sel ] ) {
                            matches.push( handleObj );
                        }
                    }
                    if ( matches.length ) {
                        handlerQueue.push({ elem: cur, handlers: matches });
                    }
                }
            }
        }
    
        //  , 
        if ( delegateCount < handlers.length ) {
            handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
        }
    
        return handlerQueue;
    }

    이 부분은 전체적으로 보면 비교적 복잡하니 우리 한번 정리해 봅시다.
    이 부분은 먼저 이벤트 에이전트에 대한 판단과 처리를 했고 match를 이용하여 조건에 부합되는 이벤트 핸들을 선별하여 조건에 부합되는 모든 이벤트 핸들을 깊이와 얕은 순서대로 이벤트 대기열에 하나하나 넣었다.
    그리고 이벤트 에이전트를 처리한 후에delegateCount로 이벤트 에이전트와 직접 귀속을 구분한 다음에 직접 귀속된 이벤트 핸들을 이벤트 대기열에 넣고 최종 이벤트 대기열을 생성합니다.이렇게 해서 최종적으로 얻은 것은 의뢰 단계가 깊을수록 앞당겨 집행되는 이벤트 대기열이다.
    따라서 사건 의뢰는 이 단계에서 이미 끝났다.또한 jQuery의 이벤트 처리 메커니즘은 이런 대기열의 형식이기 때문에 앞서 제1장 말미에서 언급한 집행 순서에 대한 문제도 여기서 잘 해결되었다.

    이벤트 대기열에 대한 디스패치 처리를 다시 보십시오


    마지막으로 디스패치에서 이 사건 대기열을 어떻게 처리하는지 살펴봅시다.
    //  
    i = 0;
    while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
        event.currentTarget = matched.elem;
    
        j = 0;
        while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
    
            if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
    
                event.handleObj = handleObj;
                event.data = handleObj.data;
    
                  // 
                ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
                    .apply( matched.elem, args );
    
                  // return false, event.preventDefault stopPropagation
                if ( ret !== undefined ) {
                    if ( (event.result = ret) === false ) {
                        event.preventDefault();
                        event.stopPropagation();
                    }
                }
            }
        }
    }

    이벤트 대기열에 대한 질서정연한 실행 (깊이와 얕음에서 그 자체로) 을 한 다음에 이 과정에서 수정된 jQuery 이벤트 대상을 통해 이벤트 대상의 속성을 동적으로 바꾸고 이벤트 핸들을 실행합니다.또한returnfalse 후 이벤트를 직접 호출합니다.preventDefault(), 및 이벤트.stopPropagation()이 처리되었습니다.

    요약:


    그러면 지금까지 이벤트에 대한 귀속은 이벤트의 복구 부분을 제외하고 다른 부분은 모두 읽었습니다.우리는 마지막에 가서 전체 과정을 다시 한 번 정리합시다.
  • 우선, 귀속할 때 on 방법을 사용했다. 이 과정에서 on은 우리가 귀속할 때 전달된 매개 변수를 일일이 처리하고 최종적으로 이를 jQuery에 전달했다.event.dd에서 실행합니다.
  • event.dd 부분에서 디스패치 방법을 인용하여 이벤트를 나누어 주었고 이벤트 이름과 이벤트 핸들을 채웠다
  • dispatch 부분에서 이벤트 대상을 복원하고 이벤트 핸들을 읽으며 이벤트 대기열을 가져와 처리하고 리셋을 실행합니다.

  • 그러면 다음 장에서는 jQuery 이벤트 대상의 복구와 이벤트의 복구에 대해 설명한다.

    좋은 웹페이지 즐겨찾기