webentwicklung-frage-antwort-db.com.de

Direkt vs. Delegiert - jQuery .on ()

Ich versuche, diesen besonderen Unterschied zwischen dem direkten und delegierten Ereignis zu verstehen Handler, die die Methode jQuery . on () verwenden . Insbesondere der letzte Satz in diesem Absatz:

Wenn ein selector bereitgestellt wird, wird der Ereignishandler als delegiert bezeichnet. Der Handler wird nicht aufgerufen, wenn das Ereignis direkt auf dem gebundenen Element auftritt, sondern nur für Nachkommen (innere Elemente), die dem Selektor entsprechen. jQuery sprudelt das Ereignis vom Ereignisziel bis zu dem Element, an das der Handler angehängt ist (d. h. vom innersten zum äußersten Element), und führt den Handler für alle Elemente entlang des Pfads aus, die mit dem Selektor übereinstimmen.

Was bedeutet "führt den Handler für alle Elemente aus"? Ich habe eine Testseite erstellt, um mit dem Konzept zu experimentieren. Beide folgenden Konstrukte führen jedoch zu demselben Verhalten:

$("div#target span.green").on("click", function() {
   alert($(this).attr("class") + " is clicked");
});

oder,

$("div#target").on("click", "span.green", function() {
   alert($(this).attr("class") + " is clicked");
});

Vielleicht könnte sich jemand auf ein anderes Beispiel beziehen, um diesen Punkt zu verdeutlichen? Vielen Dank.

152
moey

Fall 1 (direkt):

$("div#target span.green").on("click", function() {...});

== Hey! Ich möchte, dass jedes span.green innerhalb von div # target zuhört: Wenn Sie angeklickt werden, tun Sie X.

Fall 2 (delegiert):

$("div#target").on("click", "span.green", function() {...});

== Hey, div # target! Wenn eines Ihrer untergeordneten Elemente, die "span.green" sind, angeklickt wird, machen Sie X mit ihnen.

Mit anderen Worten ...

In Fall 1 wurde jeder dieser Bereiche einzeln angewiesen. Wenn neue Bereiche erstellt werden, haben sie die Anweisung nicht gehört und reagieren nicht auf Klicks. Jede Spanne ist direkt verantwortlich für ihre eigenen Ereignisse.

In Fall 2 wurde nur der Container angewiesen; Es ist dafür verantwortlich, Klicks im Namen seiner untergeordneten Elemente zu bemerken. Die Arbeit des Erfassens von Ereignissen war delegiert. Dies bedeutet auch, dass die Anweisung für untergeordnete Elemente ausgeführt wird, die in Zukunft erstellt werden.

364
N3dst4

Die erste Methode, $("div#target span.green").on(), bindet einen Click-Handler direkt an die Bereiche, die zum Zeitpunkt der Codeausführung mit dem Selektor übereinstimmen. Das bedeutet, dass andere Bereiche, die später hinzugefügt werden (oder deren Klasse entsprechend geändert wurde), nicht berücksichtigt wurden und keinen Klick-Handler haben. Wenn Sie später die "grüne" Klasse aus einem der Bereiche entfernen, wird der Click-Handler weiterhin ausgeführt. JQuery verfolgt nicht, wie der Handler zugewiesen wurde, und überprüft, ob der Selektor noch übereinstimmt.

Die zweite Methode, $("div#target").on(), bindet einen Klick-Handler an die übereinstimmenden Divs (auch dies gilt für diejenigen, die zu diesem Zeitpunkt übereinstimmen), aber wenn irgendwo in der Div-Funktion ein Klick auftritt, wird die Handler-Funktion verwendet wird nur ausgeführt, wenn der Klick nicht nur im div, sondern in einem untergeordneten Element aufgetreten ist, das mit dem Selektor im zweiten Parameter .on(), "span.green" übereinstimmt. Wenn Sie dies tun, spielt es keine Rolle, wann diese untergeordneten Bereiche erstellt wurden. Wenn Sie auf diese klicken, wird der Handler weiterhin ausgeführt.

Für eine Seite, die ihren Inhalt nicht dynamisch hinzufügt oder ändert, werden Sie also keinen Unterschied zwischen den beiden Methoden feststellen. Wenn Sie zusätzliche untergeordnete Elemente dynamisch hinzufügen, bedeutet die zweite Syntax, dass Sie ihnen keine Klick-Handler zuweisen müssen, da Sie dies bereits einmal für das übergeordnete Element getan haben.

5
nnnnnn

Die Erklärung von N3dst4 ist perfekt. Auf dieser Grundlage können wir annehmen, dass sich alle untergeordneten Elemente im Körper befinden. Daher müssen wir nur Folgendes verwenden:

$('body').on('click', '.element', function(){
    alert('It works!')
});

Es funktioniert mit direkten oder delegierten Ereignissen.

4

Tangential zum OP, aber das Konzept, das mir geholfen hat, die Verwirrung mit dieser Funktion zu lösen, ist das die gebundenen Elemente müssen Eltern der ausgewählten Elemente sein.

  • Gebunden bezieht sich auf das, was vom .on Übrig ist.
  • Selected bezieht sich auf das 2. Argument von .on().

Die Delegierung funktioniert nicht wie .find () und wählt eine Teilmenge der gebundenen Elemente aus. Der Selektor gilt nur für strenge untergeordnete Elemente.

$("span.green").on("click", ...

ist sehr verschieden von

$("span").on("click", ".green", ...

Insbesondere muss das gebundene Element ein permanentes übergeordnetes Element sein, um die Vorteile von @ N3dst4-Hinweisen für "Elemente, die in Zukunft erstellt werden" zu erhalten. Dann können die ausgewählten Kinder kommen und gehen.

BEARBEITEN

Checkliste, warum delegierte .on Nicht funktioniert

Heikle Gründe, warum $('.bound').on('event', '.selected', some_function) möglicherweise nicht funktioniert:

  1. Gebundenes Element ist nicht permanent. Es wurde nach dem Aufruf von .on() erstellt
  2. Das ausgewählte Element ist kein richtiges ntergeordnetes eines gebundenen Elements. Es ist das gleiche Element.
  3. Das ausgewählte Element verhinderte Sprudeln eines Ereignisses für das gebundene Element, indem .stopPropagation() aufgerufen wurde.

(Auslassen weniger kniffliger Gründe, z. B. eines falsch geschriebenen Selektors.)

2
Bob Stein

Ich habe einen Beitrag mit einem Vergleich der direkten Ereignisse verfasst und delegiert. Ich vergleiche reines js, aber es hat die gleiche Bedeutung für jquery, die es nur einschließt.

Die Schlussfolgerung ist, dass die delegierte Ereignisbehandlung für eine dynamische DOM-Struktur vorgesehen ist, in der gebundene Elemente erstellt werden können, während der Benutzer mit der Seite interagiert (es sind keine erneuten Bindungen erforderlich), und die direkte Ereignisbehandlung für statische DOM-Elemente vorgesehen ist, wenn bekannt ist, dass sich die Struktur nicht ändert.

Für weitere Informationen und einen vollständigen Vergleich - http://maciejsikora.com/standard-events-vs-event-delegation/

Es ist nicht richtig, immer delegierte Handler zu verwenden, was meines Erachtens aktuell sehr trendy ist. Viele Programmierer verwenden es, weil "es verwendet werden sollte", aber in Wahrheit sind direkte Event-Handler in bestimmten Situationen besser und die Wahl, welche Methode verwendet werden soll, sollte unterstützt werden durch Kenntnis der Unterschiede.

1
Maciej Sikora