Der effizienteste Weg, Event-Handler dynamisch zu binden

8

Problem: Ich muss eine beliebige Anzahl von Event-Handlern an eine beliebige Anzahl von Elementen (DOM-Knoten, window , document ) zur Laufzeit dynamisch binden und ich muss in der Lage sein, das Ereignis zu aktualisieren Bindung für dynamisch erstellte (oder zerstörte) Knoten während der Lebensdauer meiner Seite. Es gibt drei Optionen, die ich sehen kann, um dieses Problem anzugehen:

I) Ereignisdelegierung in window
II) Direkte Ereignisbindung für jeden Knoten
III) Ereignisdelegierung auf gemeinsamen Vorfahren (was bis zur Laufzeit unbekannt wäre und möglicherweise neu berechnet werden müsste, wenn das DOM geändert wird)

Was ist der effizienteste Weg, dies zu tun?

Ein kleiner Kontext

Ich arbeite an einer Reihe von Seiten, die Analytics-Tracking für Benutzerereignisse benötigen (Klicks, Scrolling usw.), und ich möchte diese Event-Handler einfach über mehrere Seiten hinweg konfigurieren können, ohne ein Skript schreiben zu müssen Behandeln Sie die Ereignisbindung für jede Instanz. Da ich eventuell neue Ereignisse in der Zukunft verfolgen oder Ereignisse auf Elementen verfolgen muss, die der Seite dynamisch hinzugefügt / von ihr entfernt werden, muss ich außerdem Änderungen im DOM berücksichtigen können, die während der Lebensdauer auftreten der Seite.

Als Beispiel für das, was ich gerade betrachte, möchte ich eine Funktion erstellen, die ein Konfigurationsobjekt akzeptiert, das es dem Programmierer ermöglicht, für jedes Ereignis Standardbehandlungsroutinen anzugeben und sie für bestimmte Elemente zu überschreiben:

%Vor%

Quellen

wvandaal 28.08.2014, 15:39
quelle

1 Antwort

1

Normalerweise delegiere ich Ereignisse für das Objekt document.documentElement , weil:

  1. Es repräsentiert das Element <html> auf der Seite, das alles enthält , das alle HTML-Tags enthält, mit denen der Benutzer interagieren kann.
  2. Es steht ab dem Moment zur Verfügung, an dem JavaScript ausgeführt wird, wodurch die Notwendigkeit für einen Fensterlade- oder DOM-fähigen Ereignishandler
  3. beseitigt wird
  4. Sie können weiterhin Scroll-Ereignisse erfassen

Was die Effizienz der Ereignisdelegierung anbelangt, so muss das Ereignis umso mehr aufblühen, je länger es dauert, aber wir sprechen ~ 1 bis 2 ms Zeitdifferenz - vielleicht . Es ist für den Benutzer nicht wahrnehmbar. Es ist normalerweise die Verarbeitung eines DOM-Ereignisses, die eine Leistungseinbuße einführt, nicht die Bubbling des Ereignisses von einem Knoten zu einem anderen.

Ich habe festgestellt, dass die folgenden Dinge die JavaScript-Leistung im Allgemeinen negativ beeinflussen:

  1. Je mehr Knoten Sie in der Dokumentstruktur haben, desto zeitaufwendiger ist es für den Browser, sie zu manipulieren.
  2. Je größer die Anzahl der Event-Handler auf der Seite ist, desto mehr verlangsamt sich JavaScript, obwohl Sie mehr als 100 Handler benötigen, um wirklich einen Unterschied zu erkennen.

Hauptsächlich hat # 1 die größte Wirkung. Ich denke, dass es in den meisten Fällen eine vorzeitige Optimierung ist, wenn versucht wird, einen Leistungsschub in der Ereignisbehandlung zu erzielen. Der einzige Fall, den ich sehe, um Ereignisbehandlungscode zu optimieren, ist, wenn Sie ein Ereignis haben, das mehrmals pro Sekunde ausgelöst wird (z. B. "scroll" - und "mousemove" -Ereignisse). Der zusätzliche Vorteil der Ereignisdelegierung besteht darin, dass Sie Ereignishandler nicht auf DOM-Knoten bereinigen müssen, die aus der Dokumentstruktur entfernt werden, sodass der Browser den Speicher nicht mehr sammeln kann.

(Aus den Kommentaren unten) sagte wvandell:

  

Die Leistungskosten der Ereignisdelegierung haben wenig mit dem tatsächlichen "Bubbling" von Ereignissen zu tun ... Es gibt einen Leistungseinbruch, der entsteht, wenn viele Selektoren an einen einzelnen Elternteil delegiert werden.

Das stimmt, aber denken wir an die wahrgenommene Leistung. Das Delegieren vieler Klickereignisse ist für den Benutzer nicht spürbar. Wenn Sie ein Ereignis wie scroll oder mousemove delegieren, das bis zu 50 Mal pro Sekunde ausgelöst werden kann (20 ms für die Verarbeitung des Ereignisses), kann der Benutzer ein Leistungsproblem wahrnehmen. Dies führt zu meinem Argument gegen vorzeitige Optimierungen des Event-Handler-Codes.

Viele Klickereignisse können problemlos an einen gemeinsamen Vorfahren delegiert werden, z. B. document.documentElement . Würde ich ein "mousemove" Event dort delegieren? Vielleicht. Es kommt darauf an, was sonst noch passiert und ob das delegierte "mousemove" -Ereignis ausreichend reagiert.

    
Greg Burghardt 28.08.2014 16:34
quelle