복붙노트

[JQUERY] 이 주변에 어떤 방법 - jQuery를 이벤트 핸들러는 항상이 결합 된 순서대로 실행? [복제]

JQUERY

이 주변에 어떤 방법 - jQuery를 이벤트 핸들러는 항상이 결합 된 순서대로 실행? [복제]

해결법


  1. 1.업데이트 답변

    업데이트 답변

    jQuery를 이벤트가 1.8에 저장되어있는 곳의 위치를 ​​변경했습니다. 이제 당신은 혼란에 나쁜 아이디어는 내부 API를 사용하여 주위에 이유를 알고 :)

    를 DOM 객체의 이벤트에 액세스 할 수있는 새로운 내부 API는 세계의 jQuery 객체를 통해 가능하며, 각 인스턴스에 묶여 있지, 그리고 그것은으로 (우리를 위해 "이벤트") 첫 번째 매개 변수로 DOM 요소, 그리고 키 소요 두번째 파라미터.

    jQuery._data(<DOM element>, "events");
    

    그래서 여기에 jQuery를 1.8에 대한 수정 된 코드입니다.

    // [name] is the name of the event "click", "mouseover", .. 
    // same as you'd pass it to bind()
    // [fn] is the handler function
    $.fn.bindFirst = function(name, fn) {
        // bind as you normally would
        // don't want to miss out on any jQuery magic
        this.on(name, fn);
    
        // Thanks to a comment by @Martin, adding support for
        // namespaced events too.
        this.each(function() {
            var handlers = $._data(this, 'events')[name.split('.')[0]];
            // take out the handler we just inserted from the end
            var handler = handlers.pop();
            // move it at the beginning
            handlers.splice(0, 0, handler);
        });
    };
    

    그리고 여기 놀이터입니다.

    원래 대답

    @Sean이 발견되면서, jQuery를이 요소의 데이터 인터페이스를 통해 모든 이벤트 핸들러를 제공합니다. 특히 element.data ( '이벤트'). 이 사용 당신은 항상 특정 위치에있는 이벤트 핸들러를 삽입 할 수있다 간단한 플러그인을 작성할 수 있습니다.

    다음 목록의 시작 부분에 핸들러를 삽입 그냥 않는 간단한 플러그인입니다. 당신은 쉽게 특정 위치에 항목을 삽입 할 수를 확장 할 수 있습니다. 그냥 배열을 조작하는 방법입니다. 내가 jQuery의 소스를 보지 못했다 일어나고에서 어떤 jQuery를 마법 놓치고 싶지 않기 때문에, 나는 일반적으로 첫 번째 바인드를 사용하여 처리기를 추가하고 배열을 개편.

    // [name] is the name of the event "click", "mouseover", .. 
    // same as you'd pass it to bind()
    // [fn] is the handler function
    $.fn.bindFirst = function(name, fn) {
        // bind as you normally would
        // don't want to miss out on any jQuery magic
        this.bind(name, fn);
    
        // Thanks to a comment by @Martin, adding support for
        // namespaced events too.
        var handlers = this.data('events')[name.split('.')[0]];
        // take out the handler we just inserted from the end
        var handler = handlers.pop();
        // move it at the beginning
        handlers.splice(0, 0, handler);
    };
    

    그래서 예를 들어,이 마크 업이 (여기 예)로 작동합니다 :

    <div id="me">..</div>
    
    $("#me").click(function() { alert("1"); });
    $("#me").click(function() { alert("2"); });    
    $("#me").bindFirst('click', function() { alert("3"); });
    
    $("#me").click(); // alerts - 3, then 1, then 2
    

    그러나 .DATA 때문에 ( '이벤트') 지금까지 내가 아는 한, jQuery를에 대한 업데이트는 코드를 깰 수 있기 때문에 공개 API의 일부가 아닌 경우, 예를 들어 뭔가 다른 배열에서 연결된 이벤트 변화의 기본 표현입니다.

    면책 조항 : 아무것도 :) 가능하기 때문에, 여기에 솔루션입니다,하지만 난 것 여전히 ERR처럼 이러한 항목이 계속 추가로 곧 걷잡을 수 부착 된 순서를 기억하려고, 기존 코드를 리팩토링의 측면에 점점 더 많은 이들의 이벤트를 명령했다.


  2. 2.당신은 이벤트의 사용자 정의 네임 스페이스를 할 수 있습니다.

    당신은 이벤트의 사용자 정의 네임 스페이스를 할 수 있습니다.

    $('span').bind('click.doStuff1',function(){doStuff1();});
    $('span').bind('click.doStuff2',function(){doStuff2();});
    

    당신이 그들을 트리거 할 때 그런 다음 순서를 선택할 수 있습니다.

    $('span').trigger('click.doStuff1').trigger('click.doStuff2');
    

    또는

    $('span').trigger('click.doStuff2').trigger('click.doStuff1');
    

    당신은 아직 할 수 있도록 또한, 단지 트리거 클릭 ... 그들이 구속 된 순서대로 모두를 트리거해야

    $('span').trigger('click'); 
    

  3. 3.나는 조금 파고 않았다, 그래서 아주 좋은 질문은 ... 나는 흥미되었다; 내가 해낸 갔다, 어디에 관심이있는 사람들을 위해, 여기.

    나는 조금 파고 않았다, 그래서 아주 좋은 질문은 ... 나는 흥미되었다; 내가 해낸 갔다, 어디에 관심이있는 사람들을 위해, 여기.

    라인 2361과 2392 사이의 블록은 jQuery를 1.4.2 I의 소스 코드에서 본 상대 :

    jQuery.each(["bind", "one"], function( i, name ) {
        jQuery.fn[ name ] = function( type, data, fn ) {
            // Handle object literals
            if ( typeof type === "object" ) {
                for ( var key in type ) {
                    this[ name ](key, data, type[key], fn);
                }
                return this;
            }
    
            if ( jQuery.isFunction( data ) ) {
                fn = data;
                data = undefined;
            }
    
            var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
                jQuery( this ).unbind( event, handler );
                return fn.apply( this, arguments );
            }) : fn;
    
            if ( type === "unload" && name !== "one" ) {
                this.one( type, data, fn );
    
            } else {
                for ( var i = 0, l = this.length; i < l; i++ ) {
                    jQuery.event.add( this[i], type, handler, data );
                }
            }
    
            return this;
        };
    });
    

    이 흥미로운 물건을 많이 여기에 가고 있지만, 우리가 관심이있는 부분은 라인 2384과 2388 사이입니다 :

    else {
        for ( var i = 0, l = this.length; i < l; i++ ) {
            jQuery.event.add( this[i], type, handler, data );
        }
    }
    

    때마다 우리는 그렇게 (당신이 관심이 있다면, 1557 1672로 라인)의 그 살펴 보자 ... 바인드 () 또는 1 () 우리가 실제로 jQuery.event.add ()를 호출하고 있습니다 전화

    add: function( elem, types, handler, data ) {
    // ... snip ...
            var handleObjIn, handleObj;
    
            if ( handler.handler ) {
                handleObjIn = handler;
                handler = handleObjIn.handler;
            }
    
    // ... snip ...
    
            // Init the element's event structure
            var elemData = jQuery.data( elem );
    
    // ... snip ...
    
            var events = elemData.events = elemData.events || {},
                eventHandle = elemData.handle, eventHandle;
    
            if ( !eventHandle ) {
                elemData.handle = eventHandle = function() {
                    // Handle the second event of a trigger and when
                    // an event is called after a page has unloaded
                    return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
                        jQuery.event.handle.apply( eventHandle.elem, arguments ) :
                        undefined;
                };
            }
    
    // ... snip ...
    
            // Handle multiple events separated by a space
            // jQuery(...).bind("mouseover mouseout", fn);
            types = types.split(" ");
    
            var type, i = 0, namespaces;
    
            while ( (type = types[ i++ ]) ) {
                handleObj = handleObjIn ?
                    jQuery.extend({}, handleObjIn) :
                    { handler: handler, data: data };
    
                // Namespaced event handlers
                        ^
                        |
          // There is is! Even marked with a nice handy comment so you couldn't miss it 
          // (Unless of course you are not looking for it ... as I wasn't)
    
                if ( type.indexOf(".") > -1 ) {
                    namespaces = type.split(".");
                    type = namespaces.shift();
                    handleObj.namespace = namespaces.slice(0).sort().join(".");
    
                } else {
                    namespaces = [];
                    handleObj.namespace = "";
                }
    
                handleObj.type = type;
                handleObj.guid = handler.guid;
    
                // Get the current list of functions bound to this event
                var handlers = events[ type ],
                    special = jQuery.event.special[ type ] || {};
    
                // Init the event handler queue
                if ( !handlers ) {
                    handlers = events[ type ] = [];
    
                       // ... snip ...
    
                }
    
                      // ... snip ...
    
                // Add the function to the element's handler list
                handlers.push( handleObj );
    
                // Keep track of which events have been used, for global triggering
                jQuery.event.global[ type ] = true;
            }
    
         // ... snip ...
        }
    

    이 시점에서 나는에 대한 유래를 검색 할 수 있도록이 ... 삼십분보다 더 걸릴 거라고 이해하는 것을 깨달았다

    jquery get a list of all event handlers bound to an element
    

    이상 바운드 이벤트를 반복이 답을 발견 :

    //log them to the console (firebug, ie8)
    console.dir( $('#someElementId').data('events') );
    
    //or iterate them
    jQuery.each($('#someElementId').data('events'), function(i, event){
    
        jQuery.each(event, function(i, handler){
    
            console.log( handler.toString() );
    
        });
    
    });
    

    파이어 폭스 I는 이벤트가 각 요소의 데이터 속성의 객체 볼 것을 테스트하기 (우리의 경우에 클릭)이 [some_event_name] 특성을 갖는에 GUID, 네임 스페이스하는를 각각 갖는 핸들러 객체의 배열을 위해, 첨부되고 유형 및 핸들러. "그래서는"나는 "우리가 이론적으로 [요소] .data.events에 같은 방식으로 내장 개체를 추가 할 수 있어야한다 [some_event_name] .push ([our_handler_object)., ..."생각

    그리고 내가 jQuery를 (에 대해 알고하지 않았다 새로운 무언가에 소개하고 저를 RusselUresti에 의해 게시 훨씬 더 나은 대답을 ... 내 연구 결과를 작성 완료 ... 그리고 찾아 가서 내가 바로 얼굴을보고에도 불구하고 .)

    어떤 유래가 내 소견에 적어도 인터넷에서 최고의 질의 응답 사이트임을 증거입니다.

    그래서 후손을 위하여이 게시 ... 그리고 RussellUresti 이미 잘 질문에 대답하기 때문에, 그것을 커뮤니티 위키를 표시하고있다.


  4. 4.표준 원칙은 별도의 이벤트 핸들러가 호출되는 순서에 의존하지 않아야합니다. 그들은 순서에 의존 않는 경우, 별도해서는 안됩니다.

    표준 원칙은 별도의 이벤트 핸들러가 호출되는 순서에 의존하지 않아야합니다. 그들은 순서에 의존 않는 경우, 별도해서는 안됩니다.

    그렇지 않으면, 당신은 '첫 번째'되고 다른 사람은 다음 '첫 번째'당신에게 이전과 같은 혼란에있어 다시 그들의 이벤트 핸들러를 등록으로 하나의 이벤트 핸들러를 등록합니다.


  5. 5.당신이 그 솔루션에 의존하고 더 이상 질수 있도록 .DATA ( "이벤트"), 버전 1.9 및 2.0beta에서 제거되었습니다.

    당신이 그 솔루션에 의존하고 더 이상 질수 있도록 .DATA ( "이벤트"), 버전 1.9 및 2.0beta에서 제거되었습니다.

    http://jquery.com/upgrade-guide/1.9/#data-quot-events-quot-


  6. 6.jQuery를 1.9+를 들어 Dunstkreis를 제거하고 ( '이벤트') .DATA을 언급 한 바와 같이. 하지만 당신은 (그것을 문서화되지 않은 가능성을 사용하는 것은 권장하지 않습니다) 또 다른 해킹을 사용할 수 있습니다 $ ._ 데이터 ($ (이) 갔지 (0), '이벤트') 대신 및 솔루션 아 누락에 의해 제공이 다음과 같이 표시됩니다

    jQuery를 1.9+를 들어 Dunstkreis를 제거하고 ( '이벤트') .DATA을 언급 한 바와 같이. 하지만 당신은 (그것을 문서화되지 않은 가능성을 사용하는 것은 권장하지 않습니다) 또 다른 해킹을 사용할 수 있습니다 $ ._ 데이터 ($ (이) 갔지 (0), '이벤트') 대신 및 솔루션 아 누락에 의해 제공이 다음과 같이 표시됩니다

    $.fn.bindFirst = function(name, fn) {
        this.bind(name, fn);
        var handlers = $._data($(this).get(0), 'events')[name.split('.')[0]];
        var handler = handlers.pop();
        handlers.splice(0, 0, handler);
    };
    

  7. 7.아 누락에 의해 작성된 선택한 대답은 부분적으로 만 맞습니다. $ (문서) CSTE 연구진은 ($ 대 (문서) CSTE 연구진은) 핸들러, "클릭"때문에 jQuery의 이벤트 처리의 일부 내부에, 제안 된 bindFirst 기능을 사용하면 (즉,로와 필터없이 핸들러의 혼합을하지 작동하는지 (), "버튼", 핸들러를 "클릭").

    아 누락에 의해 작성된 선택한 대답은 부분적으로 만 맞습니다. $ (문서) CSTE 연구진은 ($ 대 (문서) CSTE 연구진은) 핸들러, "클릭"때문에 jQuery의 이벤트 처리의 일부 내부에, 제안 된 bindFirst 기능을 사용하면 (즉,로와 필터없이 핸들러의 혼합을하지 작동하는지 (), "버튼", 핸들러를 "클릭").

    문제는 핸들러 배열의 첫 번째 요소 때문에이 논리와 상황이 다투지 시작 시작 나누기에 필터를 사용하지 않고 우리의 이벤트를 배치, 이러한 필터링 핸들러 될 것 JQuery와 장소 (및 기대) 것입니다. 다음과 같이 업데이트 bindFirst 기능이 있어야한다 :

    $.fn.bindFirst = function (name, fn) {
        // bind as you normally would
        // don't want to miss out on any jQuery magic
        this.on(name, fn);
    
        // Thanks to a comment by @Martin, adding support for
        // namespaced events too.
        this.each(function () {
            var handlers = $._data(this, 'events')[name.split('.')[0]];
            // take out the handler we just inserted from the end
            var handler = handlers.pop();
            // get the index of the first handler without a selector
            var firstNonDelegate = handlers.first(function(h) { return !h.selector; });
            var index = firstNonDelegate ? handlers.indexOf(firstNonDelegate)
                                         : handlers.length; // Either all handlers are selectors or we have no handlers
            // move it at the beginning
            handlers.splice(index, 0, handler);
        });
    };
    

  8. 8.크리스 Chilvers '조언은 행동의 첫 번째 코스해야하지만 때로는 우리는이 도전하게하고이 인 ... 나쁜 일을 우리에게 요구하는 타사 라이브러리를 처리하고 있습니다. IMO가 사용하는 것과 비슷 추정의 범죄입니다! CSS 중요합니다.

    크리스 Chilvers '조언은 행동의 첫 번째 코스해야하지만 때로는 우리는이 도전하게하고이 인 ... 나쁜 일을 우리에게 요구하는 타사 라이브러리를 처리하고 있습니다. IMO가 사용하는 것과 비슷 추정의 범죄입니다! CSS 중요합니다.

    아 누락의 대답에 구축, 여기에 몇 가지 추가가 그런 말로 미루어 보아. 이러한 방법은 복수의 이벤트 (예를 들면 "붙여 넣기를 keyDown의 keyup"), 핸들러의 임의의 위치 및 사후 재정렬 허용한다.

    $.fn.bindFirst = function (name, fn) {
        this.bindNth(name, fn, 0);
    }
    
    $.fn.bindNth(name, fn, index) {
        // Bind event normally.
        this.bind(name, fn);
        // Move to nth position.
        this.changeEventOrder(name, index);
    };
    
    $.fn.changeEventOrder = function (names, newIndex) {
        var that = this;
        // Allow for multiple events.
        $.each(names.split(' '), function (idx, name) {
            that.each(function () {
                var handlers = $._data(this, 'events')[name.split('.')[0]];
                // Validate requested position.
                newIndex = Math.min(newIndex, handlers.length - 1);
                handlers.splice(newIndex, 0, handlers.pop());
            });
        });
    };
    

    하나는 이전에 또는 다른 주어진 핸들러 후 주어진 핸들러를 배치 할 방법과이를 추정 할 수있다.


  9. 9.난 당신이 그것의 이벤트 버블 링 측면에 대해 이야기하고 있으리라 믿고있어. (가)뿐만 아니라 스팬 요소 말했다 것은 당신의 HTML을 볼 도움이 될 것입니다. 이 같은 핵심 동작을 변경 싶어 내가 왜 나는 모든 성가신에서 그것을 찾을 수없는, 볼 수 없습니다. 나는 코드의 두 번째 블록을가는 것이 좋습니다 :

    난 당신이 그것의 이벤트 버블 링 측면에 대해 이야기하고 있으리라 믿고있어. (가)뿐만 아니라 스팬 요소 말했다 것은 당신의 HTML을 볼 도움이 될 것입니다. 이 같은 핵심 동작을 변경 싶어 내가 왜 나는 모든 성가신에서 그것을 찾을 수없는, 볼 수 없습니다. 나는 코드의 두 번째 블록을가는 것이 좋습니다 :

    $('span').click(function (){
      doStuff2();
      doStuff1();
    });
    

    가장 중요한 것은 당신이 그림 것 같은 같은 블록의 특정 요소에 대한 모든 이벤트를 관리하는 경우 당신이 그것을 더 조직 찾을 수 있습니다 생각합니다. 이 성가신을 찾을 이유를 설명 할 수 있습니까?


  10. 10.다음의 jQuery 1.4.x를위한 솔루션이다 (불행하게도 허용 대답은 JQuery와 1.4.1을 위해 작동하지 않았다)

    다음의 jQuery 1.4.x를위한 솔루션이다 (불행하게도 허용 대답은 JQuery와 1.4.1을 위해 작동하지 않았다)

    $.fn.bindFirst = function(name, fn) {
        // bind as you normally would
        // don't want to miss out on any jQuery magic
        this.bind(name, fn);
    
        // Thanks to a comment by @Martin, adding support for
        // namespaced events too.
        var handlers = this.data('events')[name.split('.')[0]];
        // take out the handler we just inserted from the end
        var copy = {1: null};
    
        var last = 0, lastValue = null;
        $.each(handlers, function(name, value) {
            //console.log(name + ": " + value);
            var isNumber = !isNaN(name);
            if(isNumber) {last = name; lastValue = value;};
    
            var key = isNumber ? (parseInt(name) + 1) : name;
            copy[key] = value;
        });
        copy[1] = lastValue;
        this.data('events')[name.split('.')[0]] = copy;
    };
    
  11. from https://stackoverflow.com/questions/2360655/jquery-event-handlers-always-execute-in-order-they-were-bound-any-way-around-t by cc-by-sa and MIT license