jQuery: więcej niż jeden program obsługi dla tego samego zdarzenia

137

Co się stanie, jeśli powiążę dwa programy obsługi zdarzeń z tym samym zdarzeniem dla tego samego elementu?

Na przykład:

var elem = $("...")
elem.click(...);
elem.click(...);

Czy ostatni program obsługi "wygrywa", czy oba programy obsługi zostaną uruchomione?

Lecieć jak po sznurku
źródło

Odpowiedzi:

168

Oba programy obsługi będą działać, model zdarzeń jQuery zezwala na wiele programów obsługi w jednym elemencie, dlatego późniejsza procedura obsługi nie zastępuje starszej procedury obsługi.

Przewodnicy będą wykonywać w kolejności, w jakiej zostali związani .

Russ Cam
źródło
1
co się dzieje z rodzimym sposobem? i skąd tubylec wie, jak usunąć konkretny?
SuperUberDuper
1
Zgodnie z DOM Level 3 (odwołującym się do specyfikacji HTML 5), programy obsługi zdarzeń są wykonywane w kolejności, w jakiej są rejestrowane - w3.org/TR/DOM-Level-3-Events/#event-phase i w3.org/TR/ 2014 / REC-html5-20141028 /… . Procedury obsługi zdarzeń można usunąć, przekazując odwołanie do zarejestrowanego modułu obsługi
Russ Cam,
@RussCam co się stanie, jeśli ten sam program obsługi jest powiązany więcej niż raz, powiedzmy, że jQuery('.btn').on('click',handlerClick);jest wywoływany w różnych miejscach, a właściwie .offto nic innego?
techie_28
Zwróć uwagę, że w przypadku widżetów jQueryUI widgetfactory nie jest to prawdą, jeśli ustawisz moduł obsługi jako opcję. Aby wywołać zarówno stary, jak i nowy program obsługi, musisz użyć tej bindmetody. Zobacz szczegóły: learn.jquery.com/jquery-ui/widget-factory/…
Michael
@MichaelScheper, możesz edytować odpowiedź i zaktualizować o dodatkowe informacje
Russ Cam,
36

Załóżmy, że masz dwa programy obsługi, f i g , i chcesz mieć pewność, że są one wykonywane w znanej i ustalonej kolejności, a następnie po prostu je hermetyzuj:

$("...").click(function(event){
  f(event);
  g(event);
});

W ten sposób jest (z punktu widzenia jQuery) tylko jeden handler, który wywołuje f i g w określonej kolejności.

Stephan202
źródło
3
+1, hermetyzacja wewnątrz funkcji jest drogą do zrobienia. I jeszcze lepsza logika warunkowa może być zawarta w funkcji obsługi, aby kontrolować zdarzenie (a), które są wyzwalane.
Gordon Potter,
Kolekcja programów obsługi, których sekwencja jest określana programowo.
Aaron Blenkush,
17

jQuery's .bind () uruchamia się w kolejności, w jakiej został powiązany :

Gdy zdarzenie osiągnie element, zostaną wyzwolone wszystkie programy obsługi powiązane z tym typem zdarzenia dla elementu. Jeśli jest zarejestrowanych wiele programów obsługi, będą one zawsze wykonywane w kolejności, w jakiej zostały powiązane. Po wykonaniu wszystkich programów obsługi zdarzenie jest kontynuowane wzdłuż normalnej ścieżki propagacji zdarzenia.

Źródło: http://api.jquery.com/bind/

Ponieważ inne funkcje jQuery (np. .click()) Są skrótami .bind('click', handler), przypuszczam, że są one również uruchamiane w kolejności, w jakiej są powiązane.

allicarn
źródło
11

Powinieneś być w stanie użyć łańcuchów do wykonywania zdarzeń w kolejności, np .:

$('#target')
  .bind('click',function(event) {
    alert('Hello!');
  })
  .bind('click',function(event) {
    alert('Hello again!');
  })
  .bind('click',function(event) {
    alert('Hello yet again!');
  });

Myślę, że poniższy kod robi to samo

$('#target')
      .click(function(event) {
        alert('Hello!');
      })
      .click(function(event) {
        alert('Hello again!');
      })
      .click(function(event) {
        alert('Hello yet again!');
      });

Źródło: http://www.peachpit.com/articles/article.aspx?p=1371947&seqNum=3

TFM mówi również:

Gdy zdarzenie osiągnie element, zostaną wyzwolone wszystkie programy obsługi powiązane z tym typem zdarzenia dla elementu. Jeśli jest zarejestrowanych wiele programów obsługi, będą one zawsze wykonywane w kolejności, w jakiej zostały powiązane. Po wykonaniu wszystkich programów obsługi zdarzenie jest kontynuowane wzdłuż normalnej ścieżki propagacji zdarzenia.

anddoutoi
źródło
1
Ani ten kod, ani artykuł nie definiują kolejności wykonywania procedury obsługi. Tak, to jest kolejność, w której nastąpi powiązanie zdarzenia , ale kolejność wywoływania programów obsługi zdarzeń jest nadal oficjalnie niezdefiniowana.
Crescent Fresh
co? co z „Teraz, gdy nastąpi zdarzenie kliknięcia, zostanie wywołana pierwsza procedura obsługi zdarzenia, po której nastąpi druga, a po niej trzecia”. jest niejasne?
anddoutoi
i tak, wiem, że oficjalne recs tego nie definiują, a PPK już udowodnił, że realizacja zdarzenia jest losowa, ale może jQuery to naprawiło ^^
anddoutoi
Ach, przegapiłem to zdanie. W rzeczywistości autor jest źle poinformowany. jQuery nie „naprawiło” tego. Ponieważ specyfikacja nie określa formalnie zamówienia, technicznie nic nie wymaga naprawy.
Crescent Fresh
5
@CrescentFresh: Przepraszam za tak późną odpowiedź, właśnie zobaczyłem pytanie, ale chciałbym, abyś wskazał na link , jest to oficjalna dokumentacja jQuery i wyraźnie to mówiWhen an event reaches an element, all handlers bound to that event type for the element are fired. If there are multiple handlers registered, they will always execute in the order in which they were bound. After all handlers have executed, the event continues along the normal event propagation path.
Razort4x
2

Wzywani są obaj handlowcy.

Możesz myśleć o wbudowanym wiązaniu zdarzeń (np. "onclick=..."), Gdzie dużą wadą jest tylko jeden moduł obsługi, który może być ustawiony dla zdarzenia.

jQuery jest zgodny z modelem rejestracji zdarzeń DOM Level 2 :

Model DOM Event Model umożliwia rejestrację wielu detektorów zdarzeń w jednym EventTarget. Aby to osiągnąć, detektory zdarzeń nie są już przechowywane jako wartości atrybutów

Crescent Fresh
źródło
@Rich: zamówienie jest oficjalnie nieokreślone.
Crescent Fresh
2

Udało się to z powodzeniem przy użyciu dwóch metod: enkapsulacji Stephan202 i wielu detektorów zdarzeń. Mam 3 zakładki wyszukiwania, zdefiniujmy ich identyfikatory tekstu wejściowego w tablicy:

var ids = new Array("searchtab1", "searchtab2", "searchtab3");

Gdy zawartość searchtab1 się zmieni, chcę zaktualizować searchtab2 i searchtab3. Zrobiłem to w ten sposób do hermetyzacji:

for (var i in ids) {
    $("#" + ids[i]).change(function() {
        for (var j in ids) {
            if (this != ids[j]) {
                $("#" + ids[j]).val($(this).val());
            }
        }
    });
}

Wielu detektorów zdarzeń:

for (var i in ids) {
    for (var j in ids) {
        if (ids[i] != ids[j]) {
            $("#" + ids[i]).change(function() {
                $("#" + ids[j]).val($(this).val());
            });
        }
    }
}

Obie metody mi się podobają, ale programista wybrał enkapsulację, jednak działało również wiele odbiorników zdarzeń. Użyliśmy Chrome, aby to przetestować.

GeneralElektrix
źródło
1

Istnieje obejście, które gwarantuje, że jedna procedura obsługi będzie występować po drugiej: dołącz drugą procedurę obsługi do elementu zawierającego i pozwól, aby zdarzenie się pojawiło. W module obsługi dołączonym do kontenera możesz spojrzeć na event.target i zrobić coś, jeśli to ten, który Cię interesuje.

Być może surowe, ale zdecydowanie powinno działać.

David
źródło
0

jquery wykona oba programy obsługi, ponieważ zezwala na wiele programów obsługi zdarzeń. Stworzyłem przykładowy kod. Możesz tego spróbować

próbny

Vikram Rajput
źródło