17 Stimmen

Verwendung von jQuery's datastore vs. expando Eigenschaften

Ich entwickle Code mit jQuery und müssen Daten im Zusammenhang mit bestimmten DOM-Elementen zu speichern. Es gibt eine Reihe von anderen Fragen über wie um beliebige Daten mit einem HTML-Element zu speichern, aber ich bin mehr daran interessiert, warum ich eine Option der anderen vorziehen würde.

Angenommen, ich möchte, stark vereinfacht, eine Eigenschaft "lineNumber" mit jeder Zeile in einer Tabelle speichern, die "interessant" ist.

Option 1 wäre, einfach eine Expando-Eigenschaft für jedes DOM-Element festzulegen (ich hoffe, ich verwende den Begriff "Expando" richtig):

$('.interesting-line').each(function(i) { this.lineNumber = i; });

Option 2 wäre die Verwendung der Funktion data() von jQuery, um eine Eigenschaft mit dem Element zu verknüpfen:

$('.interesting-line').each(function(i) { $(this).data('lineNumber', i); });

Gibt es - abgesehen von den anderen Unzulänglichkeiten meines Beispielcodes - triftige Gründe, warum Sie eine Art der Eigenschaftsspeicherung der anderen vorziehen würden?

20voto

Sean McMillan Punkte 9808

Verwendung von $.data wird Sie vor Speicherlecks schützen.

Wenn Sie im IE ein Javascript-Objekt einer Expando-Eigenschaft eines DOM-Elements zuweisen, werden Zyklen, die diesen Link überqueren, nicht in den Müll geworfen. Wenn Ihr Javascript-Objekt einen Verweis auf das Dom-Objekt hält, wird der gesamte Zyklus undicht. Es ist durchaus möglich, am Ende mit versteckten Verweisen auf DOM-Objekte, aufgrund von Schließungen, so können Sie undicht ohne es zu merken.

Der jQuery-Datenspeicher ist so eingerichtet, dass diese Zyklen nicht entstehen. Wenn Sie ihn verwenden, werden Sie auf diese Weise keinen Speicherverlust erleiden. In Ihrem Beispiel treten keine Lecks auf, weil Sie Primitive (Zeichenketten) auf das DOM-Element legen. Wenn Sie jedoch ein komplexeres Objekt dort ablegen, besteht die Gefahr von Lecks.

使用方法 $.data Sie brauchen sich also keine Sorgen zu machen.

0 Stimmen

Das ist im Jahr 2017 sicherlich viel weniger notwendig als 2011! I denken dass der IE8 das gleiche Problem hat und dass es im IE9 behoben ist, aber ich weiß es wirklich nicht.

0 Stimmen

Es wäre wirklich praktisch, Daten direkt an Elemente anzuhängen. Viel einfacher als die Speicherlecks von jQuery aufzuspüren, die durch $.data .

0 Stimmen

Sie haben es falsch verstanden. oldIE leckt Speicher, wenn Sie Daten direkt an Elemente anhängen. $.data schützt Sie vor diesen Speicherlecks.

13voto

Crescent Fresh Punkte 111444

Wenn Sie ein Plugin erstellen, sollten Sie $.data . Wenn Sie das Attribut häufig speichern müssen und nur selten das DOM danach abfragen müssen, verwenden Sie $.data .

Update 5 Jahre später : jQuery macht pas das DOM auf der Grundlage der eingestellten Expando-Eigenschaften abfragen und hat dies auch schon seit einiger Zeit nicht mehr getan. Verwenden Sie also $.data . Es gibt keinen Grund, das DOM zu verschmutzen, wenn es keinen pragmatischen Grund dafür gibt.

0 Stimmen

Ich vermeide völlig .data() nachdem ich in seine Fallstricke geraten war. Einzelheiten .

2voto

Ken Browning Punkte 27913

Verwendung von $.data ändert das DOM nicht. Sie sollten verwenden $.data . Wenn Sie ein Plugin erstellen, sollten Sie ein Objekt in $.data mit den Eigenschaften dieses Objekts, anstatt jede dieser Eigenschaften als verschiedene Schlüssel/Wertpaare in der $.data Struktur.

2 Stimmen

Beachten Sie, dass das ist, wie die $.data Repositories arbeiten, so dass Sie nur eine zusätzliche Umleitungsebene hinzufügen. wenn Sie auf diese wegen der Namespace-Isolierung beraten, kann es genauso effektiv mit einem Plugin-spezifischen Präfix getan werden. zugegeben, dies wäre nur von Bedeutung, wenn das Speichern von vielen Daten und / oder den Zugriff auf sie auf eine enge Schleife. überall sonst, es ist eine Frage der Stilpräferenz

1 Stimmen

Ja, ich würde es vermeiden, das DOM zu ändern. IIRC, kann es einige ziemlich schlechte Speicherlecks auf einigen Browsern verursachen.

0 Stimmen

@Javier: Ich habe nur wiedergegeben, was die Dokumentation für $.data empfiehlt. Ich stimme zu, dass die zusätzliche Schicht der Umleitung nicht so wertvoll zu sein scheint, aber die Dokumentation gibt die beste Praxis an.

0voto

Robert Siemer Punkte 28819

Lassen Sie mich die Frage anders formulieren: Was sind die praktischen Unterschiede zwischen den beiden verfügbaren Datenbindungsoptionen?

Eigentlich gibt es drei Möglichkeiten:

$(e).prop('myKey', myValue);
$(e).data('myKey', myValue);
$(e).attr('data-myKey', myValue);

Anmerkung: OP's e.myKey = myValue ist praktisch dasselbe wie die .prop() Linie.

  • wenn Sie mehr als Strings benötigen, verwenden Sie .prop() d.h. Expandierungseigenschaften
  • wenn Sie DOM/CSS-Transparenz und/oder HTML-Serialisierung benötigen, verwenden Sie .attr('data-*')
  • wenn Sie beides brauchen, haben Sie Pech gehabt
  • wenn Sie nur Strings verwenden, aber kein DOM benötigen, lesen Sie weiter, um die Vor- und Nachteile selbst abzuwägen
  • Was ist mit .data() Lesen Sie die letzten beiden Absätze

Wenn Sie jemals die Daten mit serialisiertem HTML weitergeben benötigen Sie die .attr() Lösung. D.h. immer wenn Sie Dinge verwenden wie .innerHTML ou .html() oder Snippets aus Strings mit enthaltenen Daten konstruieren wollen. Das Gleiche gilt, wenn Sie CSS-Selektoren verwenden wollen wie elem[data-myKey] . Nachteil: Sie können nur Zeichenketten speichern.

Wenn Ihre Daten nicht im DOM sichtbar oder für CSS-Interaktionen verfügbar sein müssen .data() y .prop() könnte funktionieren. Ihr größter Vorteil ist: Sie kann einen beliebigen Javascript-Wert enthalten .

.prop() Der größte Nachteil ist die Möglichkeit, dass Namenskollision . Wählen Sie nur Namen, bei denen Sie sicher sein können, dass sie niemals als einheimisches Eigentum verwendet werden. Z.B.. scope als Schlüssel ist eine schlechte Idee, weil sie bei einigen HTML-Elementen existiert...

Jetzt kommt .data() . Die anderen Antworten scheinen darauf zu schwören, ich vermeide es. Die Speicherlecks im Zusammenhang mit .prop() und Expando-Eigenschaften gehören im Allgemeinen der Vergangenheit an, so dass dies keinen Vorteil mehr darstellt. Aber Sie werden gegen Namenskollisionen mit HTML-Eigenschaften abgesichert sein. Das ist ein Vorteil. Aber Sie erhalten eine Reihe von Nachteilen:

$(e).data('myKey') bezieht seinen uninitialisierten Wert aus der data-myKey Attribut, falls vorhanden, führt JSON.parse() für diese aus und manchmal gibt das zurück oder greift auf den String-Wert des Attributs zurück. Sobald Sie die $(e).data('myKey', myValue) verlieren Sie die Beziehung zu den data-myKey Attribut, das dennoch mit seinem "alten" Wert weiterlebt und im DOM und in CSS-Interaktionen angezeigt wird. Hinzu kommt, dass der von Ihnen verwendete Schlüsselname möglicherweise missbraucht wird. D.h. wenn Sie sich jemals entscheiden, alle Schlüssel-Werte über $(e).data() die Schlüssel in diesem Objekt können unterschiedlich sein.

Aus diesem Grund fehlerhaftes Verhalten (Vermischung von Expando-Eigenschaftstechnologie mit data-* Attribute) und inkonsistentes get/set-Design habe ich immer vermeiden .data() Glücklicherweise ist das leicht zu machen mit .prop() y .attr() (mit data-* Schlüssel für die Einhaltung der Vorschriften).

Wenn Sie wirklich Folgendes verwenden möchten .data() um Namenskonflikte mit einheimischen Eigenschaften zu vermeiden, rate ich: nicht mit data-* Attribute, betrachten Sie diese als etwas anderes und vermeiden Sie Namenskonflikte mit diesen. Für die automatische Vermeidung von Konflikten müssen Sie Konflikte an anderer Stelle manuell vermeiden. Tolles Design.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X