2009-07-21 7 views
16

Je développe du code à l'aide de jQuery et j'ai besoin de stocker des données associées à certains éléments DOM. Il ya beaucoup d'autres questions sur comment pour stocker des données arbitraires avec un élément html, mais je suis plus intéressé par pourquoi je choisir une option sur l'autre. Dites, pour des raisons extrêmement simplifiées, que je veux stocker une propriété "lineNumber" avec chaque ligne dans une table qui est "intéressante".Utilisation de la banque de données jQuery par rapport aux propriétés expando

Option 1 serait juste définir une propriété expando sur chaque élément DOM (j'espère que je utilise le terme « expando » à juste titre):

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

Option 2 serait d'utiliser les données de jQuery() fonction d'associer une propriété à l'élément:

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

sans tenir compte des autres défauts de mon exemple de code, y at-il de fortes raisons pour lesquelles vous choisir un moyen de stockage des propriétés sur l'autre?

Répondre

12

Si vous créez un plugin, vous devez utiliser $.data. Si vous avez besoin de stocker l'attribut souvent et avez rarement besoin d'interroger le DOM pour cela, utilisez $.data.

Cela dit que pour toutes mes applications clientes je tends vers le stockage sur mesure DOM attributs sur l'élément DOM eux-mêmes afin que je puisse les interroger plus tard en utilisant le sélecteur attribut []:

var domElement = $('.interesting-line[lineNumber=' + lineNumber + ']').get(0); 

Cela est beaucoup plus lisible que l'itération de l'ensemble enveloppé appelant .data() sur chaque élément. Souvent, j'interagis avec une autre bibliothèque tierce qui fonctionne sur un élément DOM afin d'avoir un accès rapide et facile à l'élément DOM via ce mécanisme pour que le code reste lisible. Il est aussi facile que de stocker une table de correspondance mappant lineNumbers aux éléments, cependant la technique de l'attribut expando risque moins de fuir la mémoire en comparaison, puisque vous ne stockez pas de références aux éléments DOM que vous devrez nettoyer plus tard.

Mise à jour 5 ans plus tard de lire ceci après avoir reçu un [bien mérité] downvote: s'il vous plaît ignorer le texte ci-dessus striked. jQuery ne pas interroger le DOM basé sur l'ensemble de propriétés expando, et n'a pas fait pendant un certain temps. Donc, utilisez $.data. Il n'y a aucune raison de polluer le DOM lorsqu'il n'y a pas d'utilisation pragmatique pour le faire.

+2

Il y a [un plugin jQuery] (http://plugins.jquery.com/files/jquery.dataSelector.js.txt) qui vous permet d'utiliser des sélecteurs comme dans var 'domElement = $ ('. Interesting-line: data (" lineNumber = '+ lineNumber +' ") '). get (0);' – ErikE

2

L'utilisation de $.data ne modifie pas le DOM. Vous devez utiliser $.data. Si vous créez un plugin, vous devez stocker un objet dans $.data avec des propriétés sur cet objet, plutôt que de stocker chacune de ces propriétés en tant que paires clé/valeur différentes dans la structure $.data.

+2

Notez que c'est ainsi que fonctionnent les dépôts $ .data, donc vous ajoutez juste un niveau d'indirection supplémentaire. Si vous le conseillez à cause de l'isolement de l'espace de noms, il peut tout aussi bien être fait avec un préfixe spécifique au plugin. accordé, cela ne serait significatif que si on stocke beaucoup de données et/ou qu'on y accède en boucle. ailleurs, c'est une question de préférence de style – Javier

+1

Oui, j'éviterais de modifier le DOM. IIRC, il peut causer des fuites de mémoire assez mauvais sur certains navigateurs. – seth

+0

@Javier: Je relayais ce que la documentation pour $ .data conseille. Je suis d'accord sur le fait que la couche supplémentaire d'indirection ne semble pas très valable mais que les docs énoncent ses meilleures pratiques. –

21

L'utilisation de $.data vous protège des fuites de mémoire.

Dans IE, lorsque vous affectez un objet javascript à une propriété expando sur un élément DOM, les cycles qui traversent ce lien ne sont pas récupérés. Si votre objet javascript contient une référence à l'objet dom, tout le cycle fuira. Il est tout à fait possible de se retrouver avec des références cachées aux objets DOM, à cause des fermetures, de sorte que vous pouvez fuir sans vous en rendre compte.

Le magasin de données jQuery est configuré pour empêcher la formation de ces cycles. Si vous l'utilisez, vous ne fuirez pas la mémoire de cette manière. Votre exemple ne fuira pas car vous mettez des primitives (chaînes) sur l'élément DOM. Mais si vous y mettez un objet plus complexe, vous risquez de fuir. Utilisez $.data pour ne pas avoir à vous inquiéter.

+0

Ceci s'applique uniquement à IE7-, non? – thorn

+0

Il est certainement beaucoup moins nécessaire en 2017 qu'en 2011! Je pense que IE8 a le même problème, et il est corrigé dans IE9, mais je ne sais vraiment pas. –

+0

Il serait vraiment pratique d'attacher des données directement aux éléments. Beaucoup plus simple que de rechercher les fuites de mémoire de jQuery causées par '$ .data'. – thorn

Questions connexes