jQuery: Mehr als ein Handler für dasselbe Ereignis

137

Was passiert, wenn ich zwei Ereignishandler für dasselbe Element an dasselbe Ereignis binde?

Beispielsweise:

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

"Gewinnt" der letzte Handler oder werden beide Handler ausgeführt?

Flybywire
quelle

Antworten:

168

Beide Handler werden ausgeführt. Das jQuery-Ereignismodell ermöglicht mehrere Handler für ein Element. Daher überschreibt ein späterer Handler einen älteren Handler nicht.

Die Handler werden in der Reihenfolge ausgeführt, in der sie gebunden wurden .

Russ Cam
quelle
1
Was passiert mit dem einheimischen Weg? und woher weiß der Eingeborene, wie man einen bestimmten entfernt?
SuperUberDuper
1
Gemäß DOM Level 3 (unter Bezugnahme auf die HTML 5-Spezifikation) werden Ereignishandler in der Reihenfolge ausgeführt, in der sie registriert sind - w3.org/TR/DOM-Level-3-Events/#event-phase und w3.org/TR/ 2014 / REC-html5-20141028 /… . Event-Handler können entfernt werden, indem ein Verweis auf den registrierten Handler übergeben wird
Russ Cam
@RussCam Was passiert, wenn ein und derselbe Handler mehr als einmal gebunden jQuery('.btn').on('click',handlerClick);ist .off? Sagen wir einfach, er wird an verschiedenen Stellen aufgerufen, ohne dass dies tatsächlich der Fall ist.
Techie_28
Beachten Sie, dass dies für jQueryUI-Widgetfactory-Widgets nicht der Fall ist, wenn Sie den Handler als Option festlegen. Damit sowohl der alte als auch der neue Handler aufgerufen werden können, müssen Sie die bindMethode verwenden. Siehe dies für Details: learn.jquery.com/jquery-ui/widget-factory/…
Michael Scheper
@ MichaelScheper zögern Sie nicht, die Antwort zu bearbeiten und mit zusätzlichen Informationen zu aktualisieren
Russ Cam
36

Angenommen, Sie haben zwei Handler, f und g , und möchten sicherstellen, dass sie in einer bekannten und festen Reihenfolge ausgeführt werden, und kapseln sie dann einfach:

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

Auf diese Weise gibt es (aus Sicht von jQuery) nur einen Handler, der f und g in der angegebenen Reihenfolge aufruft .

Stephan202
quelle
3
+1, Kapselung innerhalb einer Funktion ist der richtige Weg. Eine noch bessere bedingte Logik kann in der Handlerfunktion enthalten sein, um die ausgelösten Ereignisse zu steuern.
Gordon Potter
Eine Sammlung von Handlern, deren Reihenfolge programmgesteuert festgelegt wird.
Aaron Blenkush
17

.bind () von jQuery wird in der Reihenfolge ausgelöst, in der es gebunden war :

Wenn ein Ereignis ein Element erreicht, werden alle Handler ausgelöst, die an diesen Ereignistyp für das Element gebunden sind. Wenn mehrere Handler registriert sind, werden sie immer in der Reihenfolge ausgeführt, in der sie gebunden wurden. Nachdem alle Handler ausgeführt wurden, wird das Ereignis auf dem normalen Ereignisausbreitungspfad fortgesetzt.

Quelle: http://api.jquery.com/bind/

Da die anderen Funktionen von jQuery (z. .click()B.) Verknüpfungen sind .bind('click', handler), würde ich vermuten, dass sie auch in der Reihenfolge ausgelöst werden, in der sie gebunden sind.

Allicarn
quelle
11

Sie sollten in der Lage sein, die Ereignisse mithilfe der Verkettung nacheinander auszuführen, z. B.:

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

Ich denke, der folgende Code macht dasselbe

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

Quelle: http://www.peachpit.com/articles/article.aspx?p=1371947&seqNum=3

TFM sagt auch:

Wenn ein Ereignis ein Element erreicht, werden alle Handler ausgelöst, die an diesen Ereignistyp für das Element gebunden sind. Wenn mehrere Handler registriert sind, werden sie immer in der Reihenfolge ausgeführt, in der sie gebunden wurden. Nachdem alle Handler ausgeführt wurden, wird das Ereignis auf dem normalen Ereignisausbreitungspfad fortgesetzt.

anddoutoi
quelle
1
Weder dieser Code noch dieser Artikel definieren eine Reihenfolge der Handlerausführung. Ja, das ist die Reihenfolge der Veranstaltung verbindlich auftreten, aber die Reihenfolge der Event - Handler aufgerufen wird offiziell noch nicht definiert.
Crescent Fresh
ehh? Was ist mit "Jetzt, wenn das Klickereignis auftritt, wird der erste Ereignishandler aufgerufen, gefolgt vom zweiten, gefolgt vom dritten." ist unklar?
anddoutoi
und ja, ich weiß, dass die offiziellen Recs dies nicht definieren und PPK hat bereits bewiesen, dass die Ereignisausführung zufällig ist, aber vielleicht hat jQuery dies behoben ^^
anddoutoi
Ahh, ich habe diesen Satz verpasst. In der Tat ist der Autor falsch informiert. jQuery hat dies nicht "behoben". Da die Spezifikation die Reihenfolge nicht formal definiert, muss technisch nichts korrigiert werden.
Crescent Fresh
5
@CrescentFresh: Entschuldigung für eine so späte Antwort, ich habe gerade die Frage gesehen, aber ich möchte, dass Sie auf einen Link verweisen . Es ist eine offizielle Dokumentation von jQuery und es steht klar, dassWhen 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

Beide Handler werden gerufen.

Möglicherweise denken Sie an eine Inline-Ereignisbindung (z. B. "onclick=..."), bei der ein großer Nachteil darin besteht, dass nur ein Handler für ein Ereignis festgelegt werden kann.

jQuery entspricht dem DOM Level 2-Ereignisregistrierungsmodell :

Das DOM-Ereignismodell ermöglicht die Registrierung mehrerer Ereignis-Listener auf einem einzelnen EventTarget. Um dies zu erreichen, werden Ereignis-Listener nicht mehr als Attributwerte gespeichert

Halbmond frisch
quelle
@Rich: Die Bestellung ist offiziell undefiniert.
Crescent Fresh
2

Mit den beiden Methoden erfolgreich funktioniert: Stephan202s Kapselung und mehrere Ereignis-Listener. Ich habe 3 Suchregisterkarten. Definieren wir deren Eingabetext-IDs in einem Array:

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

Wenn sich der Inhalt von searchtab1 ändert, möchte ich searchtab2 und searchtab3 aktualisieren. Haben Sie es für die Kapselung so gemacht:

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

Mehrere Ereignis-Listener:

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

Ich mag beide Methoden, aber der Programmierer hat die Kapselung gewählt, jedoch haben auch mehrere Ereignis-Listener funktioniert. Wir haben Chrome verwendet, um es zu testen.

GeneralElektrix
quelle
1

Es gibt eine Problemumgehung, um sicherzustellen, dass ein Handler nach dem anderen ausgeführt wird: Fügen Sie den zweiten Handler einem enthaltenden Element hinzu und lassen Sie das Ereignis in die Luft sprudeln. In dem an den Container angehängten Handler können Sie event.target anzeigen und etwas tun, wenn es das ist, an dem Sie interessiert sind.

Roh vielleicht, aber es sollte definitiv funktionieren.

David
quelle
0

jquery führt beide Handler aus, da mehrere Ereignishandler zulässig sind. Ich habe Beispielcode erstellt. Du kannst es versuchen

Demo

Vikram Rajput
quelle