sourcecode

jQuery로 바인딩된 이벤트 순서 지정 방법

codebag 2023. 9. 5. 20:13
반응형

jQuery로 바인딩된 이벤트 순서 지정 방법

제가 4개의 스크립트 블록을 포함할 수 있는 페이지를 가진 웹 앱을 가지고 있다고 가정해 보겠습니다. 제가 작성한 스크립트는 이러한 블록 중 하나에서 찾을 수 있지만 컨트롤러에서 처리하는 스크립트가 무엇인지는 모르겠습니다.

나는 몇 개를 묶습니다.onclick이벤트를 버튼으로 전송합니다. 하지만 때때로 예상치 못한 순서로 실행됩니다.

질서를 보장할 수 있는 방법이 있습니까, 아니면 과거에 이 문제를 어떻게 처리하셨습니까?

순서가 중요한 경우 직접 이벤트를 만들고 다른 콜백에 의해 이벤트가 트리거될 때 콜백을 바인딩하여 실행할 수 있습니다.

$('#mydiv').click(function(e) {
    // maniplate #mydiv ...
    $('#mydiv').trigger('mydiv-manipulated');
});

$('#mydiv').bind('mydiv-manipulated', function(e) {
    // do more stuff now that #mydiv has been manipulated
    return;
});

적어도 그런 것들은.

모든 콜백이 항상 존재하고 서로 의존하는 것에 만족한다면 Dowski의 방법은 좋습니다.

그러나 콜백을 서로 독립적으로 사용하려면 버블링을 활용하고 후속 이벤트를 상위 요소에 대리인으로 연결할 수 있습니다.상위 요소의 처리기는 해당 요소의 처리기 이후에 트리거되어 문서까지 계속됩니다.이것은 당신이 사용할 수 있는 것처럼 꽤 좋습니다.event.stopPropagation(),event.preventDefault()등은 처리기를 건너뛰고 수행을 취소하거나 취소합니다.

$( '#mybutton' ).click( function(e) { 
    // Do stuff first
} );

$( '#mybutton' ).click( function(e) { 
    // Do other stuff first
} );

$( document ).delegate( '#mybutton', 'click', function(e) {
    // Do stuff last
} );

또는 Nick Leachs bindLast 플러그인을 사용하여 이벤트를 마지막으로 바인딩할 수 있습니다. https://github.com/nickyleach/jQuery.bindLast

또는 jQuery 1.5를 사용하는 경우 새 지연 개체를 사용하여 영리한 작업을 수행할 수도 있습니다.

저는 이런 종류의 과정을 일반화하기 위해 오랫동안 노력해 왔지만, 저의 경우에는 체인의 첫 번째 이벤트 청취자의 순서에만 관심이 있었습니다.

사용할 수 있는 경우 항상 다른 사용자보다 먼저 트리거되는 이벤트 수신기를 바인딩하는 myjQuery 플러그인이 있습니다.

jQuery 변경 사항에 따라 업데이트됨(Toskan 덕분) **

(function($) {
    $.fn.bindFirst = function(/*String*/ eventType, /*[Object])*/ eventData, /*Function*/ handler) {
        var indexOfDot = eventType.indexOf(".");
        var eventNameSpace = indexOfDot > 0 ? eventType.substring(indexOfDot) : "";

        eventType = indexOfDot > 0 ? eventType.substring(0, indexOfDot) : eventType;
        handler = handler == undefined ? eventData : handler;
        eventData = typeof eventData == "function" ? {} : eventData;

        return this.each(function() {
            var $this = $(this);
            var currentAttrListener = this["on" + eventType];

            if (currentAttrListener) {
                $this.bind(eventType, function(e) {
                    return currentAttrListener(e.originalEvent); 
                });

                this["on" + eventType] = null;
            }

            $this.bind(eventType + eventNameSpace, eventData, handler);

            var allEvents = $this.data("events") || $._data($this[0], "events");
            var typeEvents = allEvents[eventType];
            var newEvent = typeEvents.pop();
            typeEvents.unshift(newEvent);
        });
    };
})(jQuery);

주의할 사항:

  • 이것은 완전히 테스트되지 않았습니다.
  • jQuery 프레임워크의 내부는 변경되지 않습니다(1.5.2에서만 테스트됨).
  • 소스 요소의 특성으로 바인딩되거나 jQuery bind() 및 기타 관련 함수를 사용하는 것 이외의 방식으로 바인딩된 이벤트 수신기 전에 반드시 트리거되지는 않습니다.

바인딩된 콜백이 호출되는 순서는 각 jQuery 개체의 이벤트 데이터에 의해 관리됩니다.해당 데이터를 직접 보고 조작할 수 있는 기능은 없습니다. bind() 및 unbind()(또는 이와 동등한 도우미 기능)만 사용할 수 있습니다.

Dowski의 방법이 가장 좋습니다. "첫 번째" 콜백이 "실제" 이벤트에 바인딩된 상태에서 순서가 지정된 사용자 지정 이벤트 시퀀스에 바인딩되도록 다양한 바인딩된 콜백을 수정해야 합니다.이렇게 하면 순서에 상관없이 순서가 올바른 방식으로 실행됩니다.

제가 볼 수 있는 유일한 대안은 여러분이 정말로 생각하고 싶지 않은 것입니다. 만약 여러분이 함수의 바인딩 구문이 여러분 앞에서 바인딩되었다는 것을 안다면, 모든 함수의 바인딩을 해제하고 적절한 순서로 다시 바인딩하려고 시도하십시오.이제 코드가 중복되었기 때문에 문제를 제기하는 것입니다.

jQuery를 사용하면 객체의 이벤트 데이터에서 바인딩된 이벤트의 순서를 간단히 변경할 수 있지만, 가능하지 않을 것 같은 jQuery 코어에 연결할 코드를 작성하지 않아도 됩니다.그리고 아마 제가 생각하지 못했던 이것을 허용하는 것에 대한 암시가 있을 것이고, 그래서 의도적으로 누락된 것일 수도 있습니다.

jQuery 환경에서는 버전 1.8부터 이를 다르게 구현해야 합니다.다음 릴리스 노트는 jQuery 블로그에서 가져온 것입니다.

.data("events"): jQuery는 이벤트 관련 데이터를 각 요소의 이벤트(대기)라는 데이터 개체에 저장합니다.이것은 내부 데이터 구조이므로 1.8에서는 동일한 이름의 항목과 충돌하지 않도록 사용자 데이터 이름 공간에서 제거됩니다.jQuery의 이벤트 데이터는 jQuery를 통해 계속 액세스할 수 있습니다._data(substant, "substance")

우리는 jQuery 우주에서 핸들러가 실행되는 순서를 완전히 제어합니다.Ricoo는 위에서 이것을 지적합니다.그의 대답이 그에게 많은 사랑을 얻은 것처럼 보이지는 않지만, 이 기술은 매우 유용합니다.예를 들어 라이브러리 위젯의 일부 핸들러보다 먼저 자신의 핸들러를 실행해야 하거나 위젯의 핸들러에 대한 호출을 조건부로 취소할 수 있는 권한이 필요한 경우를 생각해 보십시오.

$("button").click(function(e){
    if(bSomeConditional)
       e.stopImmediatePropagation();//Don't execute the widget's handler
}).each(function () {
    var aClickListeners = $._data(this, "events").click;
    aClickListeners.reverse();
});
function bindFirst(owner, event, handler) {
    owner.unbind(event, handler);
    owner.bind(event, handler);

    var events = owner.data('events')[event];
    events.unshift(events.pop());

    owner.data('events')[event] = events;
}

처리기를 정상적으로 바인딩한 다음 실행:

element.data('events').action.reverse();

예를 들어 다음과 같습니다.

$('#mydiv').data('events').click.reverse();

다음과 같은 방법을 사용할 수 있습니다.

/**
  * Guarantee that a event handler allways be the last to execute
  * @param owner The jquery object with any others events handlers $(selector)
  * @param event The event descriptor like 'click'
  * @param handler The event handler to be executed allways at the end.
**/
function bindAtTheEnd(owner,event,handler){
    var aux=function(){owner.unbind(event,handler);owner.bind(event,handler);};
    bindAtTheStart(owner,event,aux,true);

}
/**
  * Bind a event handler at the start of all others events handlers.
  * @param owner Jquery object with any others events handlers $(selector);
  * @param event The event descriptor for example 'click';
  * @param handler The event handler to bind at the start.
  * @param one If the function only be executed once.
**/
function bindAtTheStart(owner,event,handler,one){
    var eventos,index;
    var handlers=new Array();
    owner.unbind(event,handler);
    eventos=owner.data("events")[event];
    for(index=0;index<eventos.length;index+=1){
        handlers[index]=eventos[index];
    }
    owner.unbind(event);
    if(one){
        owner.one(event,handler);
    }
    else{
        owner.bind(event,handler);
    }
    for(index=0;index<handlers.length;index+=1){
        owner.bind(event,ownerhandlers[index]);
    }   
}

저도 같은 문제가 있어서 이 주제를 찾았습니다.위의 답변들은 그 문제들을 해결할 수 있지만, 저는 그것들이 좋은 계획이라고 생각하지 않습니다.

현실 세계에 대해 생각해 봅시다.

만약 우리가 그 대답들을 사용한다면, 우리는 우리의 코드를 바꿔야 합니다.코드 스타일을 변경해야 합니다. 다음과 같은 것이 있습니다.

원본:

$('form').submit(handle);

해킹:

bindAtTheStart($('form'),'submit',handle);

시간이 지남에 따라, 당신의 프로젝트에 대해 생각해보세요.코드는 못생기고 읽기 어렵습니다! 앤토어 이유는 단순합니다. 항상 더 좋습니다.bindAt가 10개인 경우시작, 버그가 없을 수도 있습니다.bindAt가 100개인 경우시작, 정말 제대로 정리할 수 있다고 확신하십니까?

동일한 이벤트를 여러 개 바인딩해야 하는 경우.js-file 또는 js-code load order를 제어하는 것이 가장 좋은 방법이라고 생각합니다. jquery는 이벤트 데이터를 큐로 처리할 수 있습니다.주문은 선착순입니다.코드를 변경할 필요가 없습니다.로드 순서만 변경합니다.

다음은 다양한 버전의 jQuery를 다루는 방법입니다.

// Binds a jQuery event to elements at the start of the event chain for that type.
jQuery.extend({
    _bindEventHandlerAtStart: function ($elements, eventType, handler) {
        var _data;

        $elements.bind(eventType, handler);
        // This bound the event, naturally, at the end of the event chain. We
        // need it at the start.

        if (typeof jQuery._data === 'function') {
            // Since jQuery 1.8.1, it seems, that the events object isn't
            // available through the public API `.data` method.
            // Using `$._data, where it exists, seems to work.
            _data = true;
        }

        $elements.each(function (index, element) {
            var events;

            if (_data) {
                events = jQuery._data(element, 'events')[eventType];
            } else {
                events = jQuery(element).data('events')[eventType];
            }

            events.unshift(events.pop());

            if (_data) {
                jQuery._data(element, 'events')[eventType] = events;
            } else {
                jQuery(element).data('events')[eventType] = events;
            }
        });
    }
});

일부 특수한 경우 클릭 이벤트가 바인딩되는 방식을 변경할 수 없고(이벤트 바인딩은 다른 사람의 코드에서 만들어짐) HTML 요소를 변경할 수 없는 경우 다음과 같은 해결책이 있습니다(경고: 이벤트 바인딩에 권장되는 방법이 아닙니다. 다른 개발자가 이를 위해 사용자를 살해할 수 있습니다).

<span onclick="yourEventHandler(event)">Button</span>

이 바인딩 방법을 사용하면 이벤트 핸들러가 먼저 추가되므로 이벤트 핸들러가 먼저 실행됩니다.

JQuery 1.5는 약속을 소개하며, 여기 실행 순서를 제어하는 가장 간단한 구현이 있습니다.전체 설명서는 http://api.jquery.com/jquery.when/ 에서 확인할 수 있습니다.

$.when( $('#myDiv').css('background-color', 'red') )
 .then( alert('hi!') )
 .then( myClickFunction( $('#myID') ) )
 .then( myThingToRunAfterClick() );

언급URL : https://stackoverflow.com/questions/290254/how-to-order-events-bound-with-jquery

반응형