Seitdem ich den Artikel Dynamic Page / Replacing Content veröffentlicht habe, erhalte ich viele E-Mails von Leuten, die versuchen, ihn in Verbindung mit anderen JavaScript-Funktionen zu verwenden und dabei Schwierigkeiten haben. Meistens handelt es sich um eine Art Lightbox-Effekt. Eine ihrer Seiten enthält eine Reihe von Thumbnails, und wenn sie diese Seite laden, funktioniert der Lightbox-Effekt nicht.
Das Problem ist, dass die Thumbnails, wenn sie auf die Seite geladen werden (per Ajax, d. h. mit der .load()-Funktion von jQuery), keine Ereignisse an sich gebunden haben.
/* Your lightbox plugin */
$("photos a").ceebox();
/* Basics of Ajax */
$("nav a").click(function(e) {
e.preventDefault();
$("#main-content").load(this.href); /* Thumbnails loaded from here */
});
Die Funktionsweise des Lightbox-Plugins (wahrscheinlich) besteht darin, dass es beim Laden der Seite Klick-Ereignisse an die Elemente bindet, die Sie als Selektor übergeben haben (die Thumbnails), und diese Klick-Ereignisse führen die Lightbox-Aktion aus. Da die neu geladenen Thumbnails keinen Klick-Event haben, funktioniert die Lightbox-Aktion nicht.
Eine Möglichkeit, dies zu beheben, ist, das Lightbox-Plugin nach dem Laden des Inhalts aufzurufen, in der Callback-Funktion der load-Funktion.
$("photos a").ceebox();
$("nav a").click(function(e) {
e.preventDefault();
$("#main-content").load(this.href, function() {
/* Callback function */
$("photos a").ceebox(); /* Call this again */
});
});
Ein wenig repetitiv, aber das erledigt die Aufgabe.
Ein besserer Weg mit Delegate
Obwohl dies "einfach die Funktionsweise von JavaScript" ist, ist es ein bekannter Schmerzpunkt. Da jQuery eine Bibliothek ist, die existiert, um solche Probleme zu lindern, hat sie natürlich einen besseren Weg. Dieser Weg ist die Funktion .delegate(), bei der Sie anstatt Ereignisse an einzelne Elemente zu binden, ein Ereignis an ein Element höher im DOM-Baum binden, das wahrscheinlich nicht per Ajax ersetzt wird, und das auf diese Klicks achtet.
Dies beruht auf etwas, das als Event Bubbling bekannt ist, ein nettes und wichtiges Konzept in JavaScript (wirklich: das DOM-Modell). Wenn Sie auf ein Thumbnail klicken, wird ein Klick-Ereignis für dieses Element ausgelöst, dann ein Klick-Ereignis für sein übergeordnetes Element und ein Klick-Ereignis für das übergeordnete Element seines übergeordneten Elements, bis hin zum Wurzelelement. Aus diesem Grund können wir von höheren Elementen aus auf Klicks auf tiefere Elemente warten.
Leider müssten Sie in unserem Lightbox-Beispiel das Plugin selbst ändern, um es dazu zu bringen, Delegate anstelle der direkten Bindung an die Elemente zu verwenden. Das ist definitiv machbar, aber schwieriger, da Sie wahrscheinlich nicht so gut mit dem Code dieses Plugins vertraut sind wie mit Ihrem eigenen.
Hören Sie auf Remy Sharp
Während dieser Artikel entworfen wurde, veröffentlichte Remy Sharp einen Video-Screencast zu genau diesem Thema. Er kann es viel besser erklären als ich, also schauen Sie sich das unbedingt an.
Ich denke, die Erklärung des Unterschieds zwischen $(...).live(); und $(...).delegate(); wäre ein guter nächster Schritt für diesen Artikel. Denn Sie könnten ...
um dasselbe zu tun.
Die Erklärung, was Delegate tut im Vergleich zu dem, was Live tut, wäre für die meisten Leute hilfreich.
- Nur ein Gedanke
Ich bin ziemlich sicher, dass der Unterschied darin besteht, dass .live() das Ereignis automatisch an das Dokument bindet. Das bedeutet, dass Ereignisse bis dorthin aufsteigen müssen, um behandelt zu werden. Das ist weniger effizient als bei delegate, wo Sie an das Element binden können, nur so hoch wie nötig.
Schlagen Sie mich, wenn ich falsch liege.
Genau, Chris. Die .delegate()-Funktion ist viel effizienter.
Außerdem können Sie mit .live() keine Verkettung verwenden, was lästig sein kann.
Ab Version 1.4 können Sie live dazu zwingen, bei einem bestimmten Element anzuhalten, obwohl ein Blick in den Code zeigt, dass es deutlich umständlicher ist als delegate.
Ein weiterer Vorteil von delegate ist jedoch, dass Sie Selektoren verketten können, was Ihnen Flexibilität bei der Einschränkung des Geltungsbereichs des Ereignisses bietet.
@chris
Ich verstehe es nicht. Das Ereignis steigt trotzdem auf, unabhängig davon, ob ein Event Listener angehängt ist. Wie erhöht das Anhängen des Event Listeners weiter unten in der Kette die Leistung?
Der einzige Weg, wie ich das sehe (schlagen Sie *mich*, wenn ich falsch liege), ist, dass live, da es an das Wurzelelement gebunden wird, *jeden einzelnen Klick auf der Seite* abhört und dann prüft, ob das Zielelement das im Selektor angegebene war. Das ist meiner Meinung nach der größte Leistungsabfall. Es ist sogar noch schlimmer für $(‘#whatever’).live(‘hover’, function…, da es überall weiter auf Ihre Mausbewegungen auf der Seite achtet!!!
Bitte korrigieren Sie mich, wenn ich falsch liege ...
Ich DENKE..., dass beim Binden des Ereignisses am Dokument jeder einzelne Schritt nach unten überprüft werden muss, um das Element zu finden, auf das reagiert werden soll. Denn offensichtlich löst nicht jeder Klick auf das Dokument das Ereignis aus, man möchte nur, dass es ausgelöst wird, wenn es ein Klick innerhalb des von Ihnen angegebenen Elements ist. Diese rekursive Überprüfung macht es weniger effizient.
@chris
So wie ich es sehe (wiederum nicht, weil ich den Code gelesen habe, sondern weil ich glaube, dass er so implementiert ist)
Wenn Sie live/delegate verwenden, tut es im Hintergrund Folgendes: Es hängt einen Ereignis-Listener an das angegebene Eltern-Element (oder die Wurzel), etwas in der Art von (unter der Annahme, dass Sie einen ID-Selektor verwenden. Jeder andere Selektor macht es etwas komplizierter)
$('#ancestor').click(function(e){
if(e.target === $('#descendant')[0]) {
// führe deine anonyme Funktion aus
}
});
sodass es nicht notwendig ist, dieses Element zu *suchen*.
Auch hier ist dies *nicht* das, was ich aus dem Code extrahiert habe, sondern nur meine Annahme.
Korrigieren Sie mich, wenn ich falsch liege...
@joseph, vielleicht kannst du 5 Minuten auf Google verbringen und deine eigene Frage beantworten?
http://www.alfajango.com/blog/the-difference-between-jquerys-bind-live-and-delegate/
Gibt eine sehr gute Erklärung.
Was Sie mit delegate tun könnten, ist so etwas wie
Damit, wenn ich mich nicht komplett irre, wenn das Element „nav“ in Ihre Seite geladen wird, das load-Ereignis ausgelöst wird und Sie dann darin Ihre Lightbox oder ein anderes Plugin aufrufen können. (Ich konnte diesen Codeausschnitt nicht genau testen, aber
Eine weitere Alternative wäre, dies in Ihrer AJAX-Callback-Funktion aufzurufen. Auf diese Weise stellen Sie auch sicher, dass der gesamte DOM geladen ist und alle Bilder an ihrem Platz sind, bevor Sie das Plugin aufrufen.
Auf jeden Fall, netter Artikel Chris!
Ich habe das jetzt nicht getestet (poste vom iPhone), aber ich glaube nicht, dass das 'load'-Ereignis aufsteigt...
Ich kann das nicht beheben: Ich möchte per Klickfunktion von jQuery Instanzen von class="display" in class="displaynone" ändern, wenn der Benutzer auf 'next' oder 'previous' klickt. Habe versucht, dem zu folgen, was dieser Artikel gesagt hat, aber es ergibt für mich keinen Sinn. Jede Hilfe wäre äußerst willkommen.
Das Skript in meinem ist
Und mein Body-Markup ist
Ich habe versucht, .mousedown zu verwenden, da es wahrscheinlich nicht von Lightbox gebunden wurde. Hat nicht funktioniert. Das habe ich versucht
Das hat auch nicht funktioniert. Ich bin wirklich ratlos
:(
Css-Tricks Community, ich brauche eure Hilfe!
JavaScript ist nicht jQuery.
Dieses Problem betrifft alle JavaScript, unabhängig von der Bibliothek. jQuery wird nur als Beispiel und Lösung verwendet.
Ich versuche seit 5 Stunden, mit diesem JavaScript Sinn zu machen.
Ich habe einige Fragen, die ich beantwortet haben möchte, wenn Sie mir helfen können. Zuerst einmal:
Ich führe das Skript aus mit
im Head-Bereich meiner Seite.
Außerdem verwende ich das Skript der dynamischen Seite über
wo ich Delegate einfügen muss, damit die Lightbox funktioniert. Ich habe es in der dynamischen Seite.js versucht, nachdem $(“nav”).delegate(“a”, “click”, function() {
aber es ist nichts passiert. Ich habe auch versucht, davor $(‘#gallery a’).lightBox(); und danach wie im ersten Beispiel, aber es ist wieder nichts passiert. Ich habe das Video gesehen und verstehe, was mit Delegate passiert.
Bitte, ich brauche eine Erklärung, um es zu verstehen, ich schaffe es nicht. Ich habe alles versucht und das Video 5 Mal angesehen, es verstanden und es klappt trotzdem nicht. Vielen Dank!
Außerdem habe ich die erste Methode ausprobiert, kann aber den Codeausschnitt, den Sie in Ihrer dynamischen Seite JS-Datei erwähnen, nicht finden, um $(‘#gallery a’).lightBox(); einzufügen. Er ist in einer separaten Datei, ist das das Problem? Ich glaube nicht. Was passiert?
Stellen Sie sicher, dass Ihr DOM geladen ist, bevor Sie Ihre Lightbox initialisieren: Wenn Sie den Code im HEAD-Tag ausführen, versuchen Sie, ihn ans Ende der Seite zu verschieben, kurz vor dem
Weiß jemand, warum Lightbox-ähnliche UX-Ereignisse Teil des Benutzererlebnisses sein könnten? Sie haben ihren Platz, wenn sie sparsam und in bestimmten Kontexten verwendet werden (z. B. Fotos, Formularfokus usw.). Es scheint, dass im Internet viele Meinungen geäußert werden, aber ich sehe selten benutzerorientierte Studien, die zeigen, ob sie das Erlebnis für das Publikum tatsächlich verbessern. Modalitäten sind unabhängig von der Implementierung durchweg problematisch.
Ich erkenne, dass Lightbox selbst nicht der Kern dieses Artikels ist. Die UX-Seite ist es wert, betrachtet zu werden, da Lightbox in Kreisen der Frontend-Webproduktion so weit verbreitet geworden ist.
Zum Nachdenken
http://www.quora.com/UX-Design/Are-lightboxes-good-UX
Einverstanden!!
Absolut wahr!
Ich bin kürzlich auf ein Problem wie dieses gestoßen, bei dem ich AJAX-Inhalte in einem modalen Fenster ausblenden/anzeigen wollte, aber ich habe es richtig gemacht: Ich habe die Klickereignisse des AJAX-Inhalts in der Callback-Funktion von .load() gebunden, und es funktioniert perfekt in allen Browsern, aber IE7 wirft einen Fehler: Objekt unterstützt keine Methode. Ich habe .delegate() oder .live() noch nicht darauf angewendet, also nehme ich an, das könnte das Problem sein – ich werde es auf jeden Fall heute Abend ausprobieren.
Ich habe .delegate() und .live() ausprobiert und die gleichen Ergebnisse erzielt – funktioniert überall außer IE7. Ich bekomme immer die gleichen zwei Fehler: "Objekt unterstützt Eigenschaft oder Methode nicht" und einen im jQuery-Quellcode: "Ausnahme ausgelöst und nicht abgefangen".
Ja, JavaScript ist einfach, aber auf grundlegender Ebene, ich bevorzuge jQuery 1000 Mal, nicht so viele Codezeilen, funktioniert sehr schnell und ist leicht zu verstehen :-) und Prototype ist auch sehr gut. Was ist Ihr Favorit: jQuery oder Proto?
Hallo zusammen,
Ich habe eine Frage dazu, wie Google, Bing und die anderen Suchmaschinen auf JavaScript reagieren. Ich habe eine Slideshow auf meiner Website, die ich mit JavaScript, ohne Flash, erstellt habe. Werden Google & Co. die Links und den Text daraus lesen können? Bitte schauen Sie sich die Slideshow an
Vielen Dank,
John
Event Bubbling ist eine Funktion des DOM-Modells des Browsers, nicht von JavaScript.
Ja, guter Punkt. Während "Ereignisse" ein JavaScript-Konzept sind, sind sie also eng damit verbunden. Ich habe eine Notiz im Artikel gemacht.
Nun, tatsächlich sind Ereignisse kein JavaScript-Konzept. Wiederum geht es um das DOM. Der Browser löst ein Ereignis für einen DOM-Knoten aus, und wenn jemand zufällig eine JS-Methode mit dem Ereignis verknüpft hat, wird diese Methode aufgerufen.
Es ist möglich, Ereignis-Handler in jeder Sprache zu implementieren, die ein Browser unterstützt. Zum Beispiel unterstützt IE JS, VBScript und C++ über COM. Wenn .net installiert ist, kann praktisch jede .net-Sprache verwendet werden.
Firefox unterstützt JS und C++ über XPCOM. Es gibt Add-ons für Firefox, die Handler in Python schreiben lassen.
Das ist genau das, was ich brauchte. Danke