Données jQuery vs Attr?

513

Quelle est la différence d'utilisation entre $.dataet $.attrlors de l'utilisation data-someAttribute?

Ma compréhension est que $.datac'est stocké dans jQuery $.cache, pas dans le DOM. Par conséquent, si je souhaite utiliser $.cachepour le stockage de données, je dois utiliser $.data. Si je veux ajouter des attributs de données HTML5, je devrais utiliser $.attr("data-attribute", "myCoolValue").

John B
la source
5
veuillez lire ceci: forum.jquery.com/topic/when-to-use-attr-vs-data
Baz1nga
14
@zzz Sauf qu'il ne semble pas vraiment répondre à la question ...?
sdleihssirhc
2
En fait, c'est le cas, indirectement. Attacher un objet via attr()peut entraîner des fuites de mémoire (au moins dans IE), tandis que l'utilisation data()est sûre. Il fait allusion à cela dans sa réponse même s'il ne le dit pas explicitement. Plus d'informations sur les documents jQuery (voir les "Notes supplémentaires"): api.jquery.com/attr
ken
6
@John B, juste FYI (même si c'est ancien), l'attribut data de data-someAttributen'est pas valide; selon les spécifications, seuls les minuscules sont autorisés. Vous rencontrerez une myriade de problèmes étranges en utilisant des caractères majuscules.
ken
1
@AdrienBe Beaucoup de références facilement trouvées via la recherche, mais puisque je m'ennuie, vous allez ici: stackoverflow.com/a/22753630/84473
ken

Réponses:

748

Si vous transmettez des données à un élément DOM à partir du serveur, vous devez définir les données sur l'élément:

<a id="foo" data-foo="bar" href="#">foo!</a>

Les données sont ensuite accessibles via .data()jQuery:

console.log( $('#foo').data('foo') );
//outputs "bar"

Cependant, lorsque vous stockez des données sur un nœud DOM dans jQuery à l' aide de données, les variables sont stockées sur l' objet nœud . Il s'agit de prendre en charge des objets et des références complexes, car le stockage des données sur l' élément de nœud en tant qu'attribut n'acceptera que les valeurs de chaîne.

Poursuivant mon exemple d'en haut:
$('#foo').data('foo', 'baz');

console.log( $('#foo').attr('data-foo') );
//outputs "bar" as the attribute was never changed

console.log( $('#foo').data('foo') );
//outputs "baz" as the value has been updated on the object

En outre, la convention de dénomination des attributs de données a un peu de "gotcha" caché:

HTML:
<a id="bar" data-foo-bar-baz="fizz-buzz" href="#">fizz buzz!</a>
JS:
console.log( $('#bar').data('fooBarBaz') );
//outputs "fizz-buzz" as hyphens are automatically camelCase'd

La clé coupée fonctionnera toujours:

HTML:
<a id="bar" data-foo-bar-baz="fizz-buzz" href="#">fizz buzz!</a>
JS:
console.log( $('#bar').data('foo-bar-baz') );
//still outputs "fizz-buzz"

Cependant, l'objet renvoyé par .data()n'aura pas la clé coupée:

$('#bar').data().fooBarBaz; //works
$('#bar').data()['fooBarBaz']; //works
$('#bar').data()['foo-bar-baz']; //does not work

C'est pour cette raison que je suggère d'éviter la clé coupée en javascript.

Pour HTML, continuez à utiliser le formulaire avec trait d'union. Les attributs HTML sont censés être automatiquement mis en minuscules ASCII , donc <div data-foobar></div>, <DIV DATA-FOOBAR></DIV>et <dIv DaTa-FoObAr></DiV>sont censés être traités comme identiques, mais pour une meilleure compatibilité, la forme minuscule doit être préférée.

La .data()méthode effectuera également une conversion automatique de base si la valeur correspond à un modèle reconnu:

HTML:
<a id="foo"
    href="#"
    data-str="bar"
    data-bool="true"
    data-num="15"
    data-json='{"fizz":["buzz"]}'>foo!</a>
JS:
$('#foo').data('str');  //`"bar"`
$('#foo').data('bool'); //`true`
$('#foo').data('num');  //`15`
$('#foo').data('json'); //`{fizz:['buzz']}`

Cette capacité de diffusion automatique est très pratique pour instancier des widgets et des plugins:

$('.widget').each(function () {
    $(this).widget($(this).data());
    //-or-
    $(this).widget($(this).data('widget'));
});

Si vous devez absolument avoir la valeur d'origine sous forme de chaîne, vous devrez utiliser .attr():

HTML:
<a id="foo" href="#" data-color="ABC123"></a>
<a id="bar" href="#" data-color="654321"></a>
JS:
$('#foo').data('color').length; //6
$('#bar').data('color').length; //undefined, length isn't a property of numbers

$('#foo').attr('data-color').length; //6
$('#bar').attr('data-color').length; //6

C'était un exemple artificiel. Pour stocker les valeurs de couleur, j'avais l'habitude d'utiliser la notation hexadécimale numérique (c'est-à-dire 0xABC123), mais il convient de noter que l' hex a été mal analysé dans les versions de jQuery avant 1.7.2 , et n'est plus analysé dans un à Numberpartir de jQuery 1.8 rc 1.

jQuery 1.8 rc 1 a changé le comportement de la coulée automatique . Avant, tout format qui était une représentation valide d'un Numberétait converti en Number. Désormais, les valeurs numériques ne sont converties automatiquement que si leur représentation reste la même. Ceci est mieux illustré par un exemple.

HTML:
<a id="foo"
    href="#"
    data-int="1000"
    data-decimal="1000.00"
    data-scientific="1e3"
    data-hex="0x03e8">foo!</a>
JS:
                              // pre 1.8    post 1.8
$('#foo').data('int');        //    1000        1000
$('#foo').data('decimal');    //    1000   "1000.00"
$('#foo').data('scientific'); //    1000       "1e3"
$('#foo').data('hex');        //    1000     "0x03e8"

Si vous prévoyez d'utiliser d'autres syntaxes numériques pour accéder aux valeurs numériques, assurez-vous de convertir la valeur en une Numberpremière, comme avec un unaire+ opérateur .

JS (suite):
+$('#foo').data('hex'); // 1000
zzzzBov
la source
17
@vitorbal, bien que cela soit vrai, l'objet renvoyé par .data()n'aura pas le formulaire avec trait d'union, donc $('#bar').data('foo-bar-baz')cela fonctionnera, mais $('#bar').data()['foo-bar-baz']pas. C'est pour cette raison que je suggère aux gens d'éviter d'utiliser le formulaire avec trait d'union.
zzzzBov
1
ok, maintenant je vois ce que tu veux dire. Je ne connaissais pas ce petit détail, merci pour la mise à jour :)
vitorbal
1
@SableFoste, quel lien? api.jquery.com/data est le lien correct pour la méthode et n'a pas changé pour autant que je sache.
zzzzBov
1
j'aime, foo, bar, baz, fizz, buzz plus: D
Usman Younas
1
J'adore chaque ligne.
Foo Bar
108

La principale différence entre les deux est où il est stocké et comment il est accessible.

$.fn.attr stocke les informations directement sur l'élément dans des attributs qui sont publiquement visibles lors de l'inspection, et qui sont également disponibles à partir de l'API native de l'élément.

$.fn.datastocke les informations dans un endroit ridiculement obscur . Il est situé dans une variable fermée sur locale appelée data_userqui est une instance d'une fonction définie localement Data. Cette variable n'est pas accessible directement depuis l'extérieur de jQuery.

Ensemble de données avec attr()

  • accessible depuis $(element).attr('data-name')
  • accessible depuis element.getAttribute('data-name'),
  • si la valeur était sous la forme data-nameégalement accessible à partir $(element).data(name)et element.dataset['name']etelement.dataset.name
  • visible sur l'élément lors de l'inspection
  • ne peut pas être des objets

Ensemble de données avec .data()

  • accessible uniquement depuis.data(name)
  • non accessible depuis .attr()ou ailleurs
  • non visible publiquement sur l'élément lors de l'inspection
  • peut être des objets
Travis J
la source
2
Oui, ma principale question était de savoir où ces données étaient stockées, alors merci pour ces informations!
Max Wilder
2
C'est également .attr()la voie à suivre, si par la suite vous souhaitez utiliser les données comme sélecteur ( .data()ne sera pas trouvé; voir codepen.io/anon/pen/EvawPV?editors=1011 )
Kamafeather
1

Vous pouvez utiliser l' data-*attribut pour incorporer des données personnalisées. ledata-* attributs nous permettent d'intégrer des attributs de données personnalisés sur tous les éléments HTML.

jQuery .data() méthode vous permet d'obtenir / définir des données de tout type sur des éléments DOM d'une manière qui est à l'abri des références circulaires et donc des fuites de mémoire.

.attr()Méthode jQuery get / set valeur d'attribut uniquement pour le premier élément de l'ensemble correspondant.

Exemple:

<span id="test" title="foo" data-kind="primary">foo</span>

$("#test").attr("title");
$("#test").attr("data-kind");
$("#test").data("kind");
$("#test").data("value", "bar");
Yogendra Chauhan
la source