Unterschied zwischen den Funktionen jQuery `click` ,` bind`,` live`, `delegate`,` trigger` und` on` (mit einem Beispiel)?

139

Ich habe die Dokumentation jeder Funktion gelesen jQuery official website, aber es gibt keine solchen Vergleichslisten zwischen den folgenden Funktionen:

$().click(fn)
$().bind('click',fn)
$().live('click',fn)
$().delegate(selector, 'click', fn)
$().trigger('click') // UPDATED
$().on('click', selector ,fn); // more UPDATED

Bitte vermeiden Sie Referenzlinks.

Wie funktionieren alle oben genannten Funktionen genau und welche sollten in welcher Situation bevorzugt werden?

Hinweis: Wenn es andere Funktionen mit derselben Funktionalität oder demselben Mechanismus gibt, gehen Sie bitte näher darauf ein.

Aktualisieren

Ich habe auch eine $.triggerFunktion gesehen. Funktioniert es ähnlich wie die oben genannten Funktionen?

Mehr Update

Jetzt .onist in v1.7 hinzugefügt und ich denke, dass diese irgendwie alle oben genannten Funktionen Anforderungen zusammen abdecken.

diEcho
quelle
3
@I Wie bei PHP stimmen die Leute manchmal ab, wenn sie nicht der Meinung sind, dass es sich um eine Frage handelt, die von einem Handbuch nicht beantwortet werden kann oder eine Hausaufgabenfrage zu sein scheint. Keine Sorge, andere Leute werden darüber abstimmen, wenn sie es nützlich finden.
Typoneerror
@ Typeoneerror - Danke für die Unterstützung, ich habe das Handbuch bereits gelesen und wenn ich den klaren Unterschied nicht verstanden habe, dann poste ich hier.
DiEcho
3
@Ich mag PHP - Die Frage wurde für ein bisschen Aufräumen bearbeitet ... dies wird oft gestellt, aber selten auf diese Weise kann es leicht eine wertvolle Google-fähige Ressource sein. Ich bin damit einverstanden, dass ein Wiki-Eintrag von so etwas sehr hilfreich wäre. Ich sehe Verwirrung darüber, insbesondere mit .live()und .delegate()fast jeden Tag +1 für eine vollkommen gültige Frage.
Nick Craver
@ Nick Craver Danke für die Bearbeitung, eigentlich bin ich schlecht in Englisch (lol). gibt es jede maunal / reference , dass , wie poste wir eine Frage auf SO. ot es kam nur aus Erfahrung
diEcho
@Ich mag PHP - Es ist ein bisschen von beidem, hier gibt es eine großartige Allround-FAQ für SO: meta.stackexchange.com/questions/7931 Für die Formulierung / Kommentare lernen Sie einfach, was passt und wie es am besten ist Übermitteln Sie Ihre Gedanken, Code> jede Beschreibung manchmal, indem Sie das richtige Schlüsselwort verwenden und entsprechend markieren. Je länger Sie hier sind, desto mehr Poster verbessern sich im Laufe der Zeit. Rufen Sie für Ihre Bearbeitung .trigger()einfach den Ereignishandler auf ... Ich werde meiner Antwort unten eine Beschreibung hinzufügen.
Nick Craver

Antworten:

162

Bevor Sie dies lesen, rufen Sie diese Liste der Ereignisse auf einer anderen Seite auf. Die API selbst ist äußerst hilfreich, und alles, was ich unten diskutiere, ist direkt von dieser Seite aus verlinkt .

Erstens .click(function)ist buchstäblich eine Abkürzung für .bind('click', function), sie sind gleichwertig. Verwenden Sie sie, wenn Sie einen Handler direkt an ein Element binden , wie folgt:

$(document).click(function() {
  alert("You clicked somewhere in the page, it bubbled to document");
});

Wenn dieses Element ersetzt oder weggeworfen wird, ist dieser Handler nicht mehr da. Auch Elemente, die nicht vorhanden waren, als dieser Code zum Anhängen des Handlers ausgeführt wurde (z. B. der Selektor hat ihn dann gefunden), erhalten den Handler nicht.

.live()und .delegate()sind ähnlich verwandt, .delegate()tatsächlich .live()intern verwendet, beide warten auf Ereignisse, um zu sprudeln. Dies funktioniert für neue und alte Elemente , sie sprudeln Ereignisse auf die gleiche Weise. Sie verwenden diese, wenn sich Ihre Elemente ändern können, z. B. wenn Sie neue Zeilen, Listenelemente usw. hinzufügen. Wenn Sie keinen übergeordneten / gemeinsamen Vorfahren haben, der auf der Seite verbleibt und zu keinem Zeitpunkt ersetzt wird, verwenden Sie .live()Folgendes:

$(".clickAlert").live('click', function() {
  alert("A click happened");
});

Wenn Sie jedoch irgendwo ein übergeordnetes Element haben, das nicht ersetzt wird (damit die Ereignishandler nicht auf Wiedersehen gehen), sollten Sie damit .delegate()wie folgt umgehen :

$("#commonParent").delegate('.clickAlert', 'click', function() {
  alert("A click happened, it was captured at #commonParent and this alert ran");
});

Dies funktioniert fast genauso wie .live(), aber das Ereignis sprudelt weniger oft, bevor es erfasst und die Handler ausgeführt werden. Eine weitere häufige Verwendung dieser beiden Methoden ist, dass sich Ihre Klasse für ein Element ändert und nicht mehr mit dem ursprünglich verwendeten Selektor übereinstimmt. Bei diesen Methoden wird der Selektor zum Zeitpunkt des Ereignisses ausgewertet. Wenn er übereinstimmt, wird der Handler ausgeführt. Damit das Element nicht mehr mit dem Selektor übereinstimmt, wird es nicht mehr ausgeführt. Mit .click()jedoch der Ereignishandler gebunden direkt am DOM - Elemente ist die Tatsache , dass es nicht paßt , was Selektor verwendet , es zu finden ist irrelevant ... das Ereignis gebunden ist und es bleiben , bis das Element weg ist, oder der Handler wird über entfernt .unbind().

Eine weitere häufige Verwendung für .live()und .delegate()ist Leistung . Wenn Sie mit vielen Elementen arbeiten, ist das Anbringen eines Klick-Handlers direkt an jedem Element teuer und zeitaufwändig. In diesen Fällen ist es wirtschaftlicher, einen einzelnen Handler einzurichten und das Sprudeln die Arbeit erledigen zu lassen. Schauen Sie sich diese Frage an, bei der es einen großen Unterschied gemacht hat. Sie ist ein gutes Beispiel für die Anwendung.


Auslösen - für die aktualisierte Frage

Es stehen zwei Hauptfunktionen zum Auslösen von Ereignishandlern zur Verfügung, die in der API unter dieselbe Kategorie "Anhang für Ereignishandler" fallen. Dies sind .trigger()und .triggerHandler(). .trigger('eventName')In den allgemeinen Ereignissen sind einige Verknüpfungen integriert, zum Beispiel:

$().click(fn); //binds an event handler to the click event
$().click();   //fires all click event handlers for this element, in order bound

Sie können hier eine Liste mit diesen Verknüpfungen anzeigen .

Der Unterschied .trigger()löst den Ereignishandler aus (meistens jedoch nicht die Standardaktion, z. B. das Platzieren des Cursors an der richtigen Stelle bei einem Klick <textarea>). Dadurch werden die Ereignishandler in der Reihenfolge ausgeführt, in der sie gebunden waren (wie es das native Ereignis tun würde), die nativen Ereignisaktionen ausgelöst und das DOM in die Luft gesprudelt.

.triggerHandler()dient normalerweise einem anderen Zweck. Hier versuchen Sie nur, die gebundenen Handler auszulösen. Dies führt nicht dazu, dass das native Ereignis ausgelöst wird, z. B. das Senden eines Formulars. Das DOM sprudelt nicht in die Luft und ist nicht verkettbar (es gibt alles zurück, was der zuletzt gebundene Ereignishandler für dieses Ereignis zurückgibt). Wenn Sie beispielsweise ein focusEreignis auslösen möchten, das Objekt jedoch nicht fokussieren möchten, möchten Sie nur, dass der Code, an den Sie gebunden sind .focus(fn), ausgeführt wird. Dies würde dies tun, während .trigger()dies das gleiche tun würde, wie das Element tatsächlich fokussieren und in die Luft sprudeln.

Hier ist ein Beispiel aus der Praxis:

$("form").submit(); //actually calling `.trigger('submit');`

Dies würde alle Submit-Handler ausführen, zum Beispiel das jQuery-Validierungs-Plugin , und dann versuchen, das zu senden <form>. Wenn Sie jedoch nur validieren möchten, da es über einen submitEreignishandler angeschlossen ist, aber nicht danach übermittelt <form>, können Sie Folgendes verwenden .triggerHandler('submit'):

$("form").triggerHandler('submit');

Das Plugin verhindert, dass der Handler das Formular sendet, indem er bombardiert, wenn die Validierungsprüfung nicht bestanden wird. Bei dieser Methode ist es uns jedoch egal, was sie tut. Unabhängig davon, ob es abgebrochen wurde oder nicht, versuchen wir nicht , das Formular zu senden. Wir wollten es nur auslösen, um es erneut zu validieren und nichts anderes zu tun. ( Haftungsausschluss: Dies ist ein überflüssiges Beispiel, da .validate()das Plugin eine Methode enthält, aber es ist eine anständige Illustration der Absicht.)

Nick Craver
quelle
Sehr ausführlich. Eine kleine Korrektur: triggerLöst kein natives Ereignis aus. Mit native meine ich ein Ereignis, das mit fireEvent(IE) oder dispatchEvent(w3c) simuliert wurde .
Crescent Fresh
@Crescent - Aktualisiert weniger zweideutig zu sein, ich meinte , dass es die nativen Ereignis ausgelöst Aktionen , wie Formulare Vorlage, Link folgende etc ... hoffentlich ist das Update klarer :)
Nick Craver
@Nick von dem, was ich lese, scheint es, als ob Ihre Einstellung sich von der live()unterscheidet, die Sie mir hier gegeben haben: stackoverflow.com/questions/3981762/… Ist 'Gewicht' bei der Verwendung immer noch ein Problemlive() ?
Yahel
@yahelc - Ja, natürlich ... diese Antwort vergleicht streng die Optionen von Ereignishandlern und ihren spezifischen Zweck. Die Gewichtskosten im Vergleich zur Anzahl der anfänglichen Bindungen im Vergleich zum dynamischen Hinzufügen zum anfänglichen Selektor sind immer noch berechtigte Bedenken. Wenn Ihre Seitenstruktur nicht so groß ist, dass Sie nicht so viele Ereignisse haben , ist alles in Ordnung. Die Sorge um das Gewicht ist direkt proportional zur Größe / Tiefe Ihrer Struktur und zur Anzahl der Ereignisse (von Der Typ, auf den Ihr .live()Anruf wartet, z. B. click), der generiert wird, da für jeden einzelne Selektoren ausgeführt werden.
Nick Craver
1
In jQuery 1.7 ist live () zugunsten von $ (document) .on () veraltet.
Synchro
28

Die ersten beiden sind gleichwertig.

// The following two statements do the same thing:
$("blah").click( function() { alert( "Click!" ); } );
$("blah").bind( "click", function() { alert( "Click!" ); } ); 

Der zweite kann jedoch verwendet werden, um gleichzeitig an mehrere Ereignisse zu binden, indem mehrere durch Leerzeichen getrennte Ereignisnamen angegeben werden:

$("blah").bind( "click mouseover mouseout", function() { alert( "Click! Or maybe mouse moved." ); } ); 

Die .liveMethode ist interessanter. Betrachten Sie das folgende Beispiel:

<a class="myLink">A link!</a>
<a id="another">Another link!</a>

<script>
    $("a.myLink").click( function() { alert( 'Click!' ); } );

    $("a#another").addClass( "myLink" );
</script>

Nachdem die zweite Zeile des Skripts ausgeführt wurde, hat der zweite Link auch die CSS-Klasse "myLink". Der Ereignishandler ist jedoch nicht vorhanden, da die Klasse zum Anhängen des Ereignisses nicht vorhanden war.

Stellen Sie sich nun vor, Sie wollten, dass es umgekehrt ist: Jedes Mal, wenn irgendwo auf der Seite ein Link mit der Klasse "myLink" angezeigt wird, soll der gleiche Ereignishandler automatisch vorhanden sein. Dies ist sehr häufig der Fall, wenn Sie Listen oder Tabellen haben, in denen Sie Zeilen oder Zellen dynamisch hinzufügen, aber möchten, dass sich alle gleich verhalten. Anstatt jedes Mal neue Aufgabenhandler zuzuweisen, können Sie die folgende .liveMethode verwenden:

<a class="myLink">A link!</a>
<a id="another">Another link!</a>

<script>
    $("a.myLink").live( "click", function() { alert( 'Click!' ); } );

    $("a#another").addClass( "myLink" );
</script>

In diesem Beispiel erhält der zweite Link auch den Ereignishandler, sobald er die Klasse "myLink" erhält. Magie! :-)

Natürlich ist es nicht so wörtlich. Was .livewirklich tut, ist, den Handler nicht an das angegebene Element selbst anzuhängen, sondern an die Wurzel des HTML-Baums (das "body" -Element). Ereignisse in DHTML haben diese lustige Funktion des "Sprudelns". Bedenken Sie:

<div> <a> <b>text</b> </a> </div>

Wenn Sie auf "Text" klicken, erhält das <b> -Element zuerst ein "Klick" -Ereignis. Danach erhält das <a> -Element ein "Klick" -Ereignis. Danach erhält das <div> -Element ein "Klick" -Ereignis. Und so weiter - bis zum <body> -Element. Und hier fängt jQuery das Ereignis ab und prüft, ob es "Live" -Handler gibt, die für das Element gelten, das das Ereignis überhaupt verursacht hat. Ordentlich!

Und schließlich die .delegateMethode. Es werden einfach alle untergeordneten Elemente Ihres Elements, die dem angegebenen Selektor entsprechen, mit einem "Live" -Handler versehen. Schau mal:

$("table").delegate( "td", "click", function() { alert( "Click!" ); } );

// Is equivalent to:
$("table").each( function() {
    $(this).find( "td" ).live( "click", function() { alert( "Click!" ); } );
} );

Fragen?

Fjodor Soikin
quelle
Um genau zu sein, .live()bindet an documentnicht <body>:) Sie können eine Demo hier ansehen, ziehen Sie einfach die Konsole hoch, um sie zu überprüfen: jsfiddle.net/aJy2B
Nick Craver
3
Es war bequemer, es so zu erklären. :-)
Fyodor Soikin
4
Fair genug für den "Körper" -Teil, aber "bis zum <body> -Element" ist falsch, Ereignisse sprudeln dort weiter vorbei und es ist nicht dort, wo .live()Handler leben, es ist darüber hinaus, auf document:) Sie können a sehen Demo dazu hier: jsfiddle.net/S2VBX
Nick Craver
8

Ab jQuery 1.7 war die .live () -Methode veraltet. Wenn Sie eine jQuery-Version <1.7 verwenden, wird offiziell empfohlen, .delegate () anstelle von .live () zu verwenden.

.live () wurde jetzt durch .on () ersetzt.

Am besten gehen Sie direkt zur jQuery-Site, um weitere Informationen zu erhalten. Hier sind jedoch die aktuellen Versionen der .on () -Methode:

.on( events [, selector] [, data], handler(eventObject) )
.on( events-map [, selector] [, data] )

http://api.jquery.com/on/

Jonathan Tonge
quelle
2

$().click(fn)und $().bind('click', fn)sind auf den ersten Blick identisch, aber die $.bindVersion ist aus zwei Gründen leistungsfähiger:

  1. $().bind()Mit dieser Option können Sie beispielsweise mehreren Ereignissen einen Handler zuweisen $().bind('click keyup', fn).
  2. $().bind()unterstützt Ereignisse mit Namespace - eine leistungsstarke Funktion, wenn Sie nur bestimmte Ereignishandler entfernen (aufheben) möchten, an die ein Element gebunden ist - lesen Sie mehr in Namespaced Events .

Live vs Delegate: Dies wurde bereits in den anderen Antworten beantwortet.

fbuchinger
quelle
1

Hier kann das Lesen der API hilfreich sein. Ich weiß es jedoch auf Anhieb, sodass Sie weiterhin faul sein können (yay!).

$('#something').click(fn);
$('#something').bind('click',fn);

Hier gibt es keinen Unterschied (den ich kenne). .clickist einfach eine Convenience / Helfer-Methode.bind('click'

// even after this is called, all <a>s in
// <div class="dynamic_els"> will continue
// to be assigned these event handlers

$('div.dynamic_els a').live(‘click’,fn);

Dies ist sehr unterschiedlich, da .livedem Selektor, den Sie übergeben (den Sie hier nicht haben) , Ereignisse hinzugefügt werden und das DOM weiterhin angezeigt wird, wenn Knoten eingefügt / entfernt werden

$('#some_element').delegate('td','click',fn);

Dies ist nur aufgrund der Art und Weise, wie Sie Ereignishandler zuweisen, anders. .delegatekonzentriert sich auf das Sprudeln von DOM-Ereignissen. Das Grundprinzip ist, dass jedes Ereignis durch den DOM-Baum nach oben sprudelt, bis es das Stammelement erreicht ( documentoder windowoder <html>oder <body>, ich kann mich nicht genau erinnern).

In beiden Fällen binden Sie einen onclickHandler an alle darin enthaltenen <td>s $('#some_element')(Sie müssen einen Selektor angeben, obwohl Sie sagen könnten $(document)). Wenn eines seiner Kinder angeklickt wird, sprudelt das Ereignis bis zum <td>. Sie können dann das Quellelement des Ereignisses extrahieren (was jQuery automatisch für Sie erledigt).

Dies ist nützlich, wenn es Unmengen von Elementen gibt und Sie nur wenige (oder einen zentralen) Punkt haben, den diese Ereignisse durchlaufen werden. Dies spart dem Browser Aufwand und Speicher, um diese Ereignishandler in weniger Objekten zu konsolidieren.

Dan Beam
quelle
1
.live() auch funktioniert off - Veranstaltung sprudelnden, in der Tat .delegate()ein Wrapper für ist .live(), es ist nur einen Kontext und die Bindung an ein Element hinzugefügt wird andere als documentdie Blasen zu erfassen. Ich denke, Ihr Verständnis der Funktionsweise der sprudelnden Handler ist etwas abweichend (dies ist meiner Meinung nach der am häufigsten missverstandene Aspekt von jQuery 1.4). Der Handler befindet sich nur auf dem Element, an das Sie ihn gebunden haben. Unabhängig davon, welches Element Sie aufgerufen .delegate()haben oder wenn ein Ereignis dorthin sprudelt, überprüft er das Ziel, um festzustellen, ob es mit dem Selektor übereinstimmt, und wird documentin diesem Fall .live()ausgeführt.
Nick Craver