jQuery Data vs Attr?

513

¿Cuál es la diferencia en el uso entre $.datay $.attrcuando se usa data-someAttribute?

Tengo entendido que $.datase almacena dentro de jQuery $.cache, no en el DOM. Por lo tanto, si quiero usar $.cachepara el almacenamiento de datos, debería usarlo $.data. Si quiero agregar atributos de datos HTML5, debería usar $.attr("data-attribute", "myCoolValue").

John B
fuente
55
por favor lea esto: forum.jquery.com/topic/when-to-use-attr-vs-data
Baz1nga
14
@zzz ¿Excepto que realmente no parece responder la pregunta ...?
sdleihssirhc
2
En realidad lo hace, indirectamente. Adjuntar un objeto a través de attr()puede provocar pérdidas de memoria (al menos en IE), mientras que el uso data()es seguro. Él insinúa esto en su respuesta, aunque no sale explícitamente y lo dice. Más información sobre los documentos de jQuery (consulte las "Notas adicionales"): api.jquery.com/attr
ken
66
@John B, solo para su información (aunque esto sea antiguo), el atributo de datos de data-someAttributeno es válido; según la especificación, solo se permiten minúsculas. Te encontrarás con una miríada de problemas extraños al usar caracteres en mayúsculas.
Ken
1
@AdrienBe Muchas de las referencias se encuentran fácilmente a través de la búsqueda, pero como estoy aburrido, aquí tienes: stackoverflow.com/a/22753630/84473
ken

Respuestas:

748

Si está pasando datos a un elemento DOM desde el servidor, debe establecer los datos en el elemento:

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

Se puede acceder a los datos utilizando .data()jQuery:

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

Sin embargo, cuando almacena datos en un nodo DOM en jQuery utilizando datos, las variables se almacenan en el objeto del nodo . Esto es para acomodar objetos complejos y referencias, ya que almacenar los datos en el elemento del nodo como un atributo solo acomodará valores de cadena.

Continuando mi ejemplo desde arriba:
$('#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

Además, la convención de nomenclatura para los atributos de datos tiene una especie de "problema" oculto:

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 clave con guiones seguirá funcionando:

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"

Sin embargo, el objeto devuelto por .data()no tendrá la clave con guiones establecida:

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

Por esta razón, sugiero evitar la clave con guiones en JavaScript.

Para HTML, siga usando el formulario con guiones. Atributos HTML se supone que para obtener automáticamente en minúsculas ASCII , por lo que <div data-foobar></div>, <DIV DATA-FOOBAR></DIV>y <dIv DaTa-FoObAr></DiV>se supone que debe ser tratada como idénticos, pero para la mejor compatibilidad se debe preferir la forma en minúsculas.

El .data()método también realizará una transmisión automática básica si el valor coincide con un patrón reconocido:

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']}`

Esta capacidad de transmisión automática es muy conveniente para instanciar widgets y complementos:

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

Si absolutamente debe tener el valor original como una cadena, deberá usar .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

Este fue un ejemplo artificial. Para almacenar valores de color, solía usar la notación hexadecimal numérica (es decir, 0xABC123), pero vale la pena señalar que el hexadecimal se analizó incorrectamente en las versiones jQuery anteriores a 1.7.2 , y ya no se analiza en NumberjQuery 1.8 rc 1.

jQuery 1.8 rc 1 cambió el comportamiento de la transmisión automática . Antes, cualquier formato que fuera una representación válida de a Numbersería enviado a Number. Ahora, los valores numéricos solo se convierten automáticamente si su representación permanece igual. Esto se ilustra mejor con un ejemplo.

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 planea usar sintaxis numéricas alternativas para acceder a los valores numéricos, asegúrese de convertir el valor a un Numberprimero, como con un +operador unario .

JS (cont.):
+$('#foo').data('hex'); // 1000
zzzzBov
fuente
17
@vitorbal, si bien esto es cierto, el objeto devuelto por .data()lo que no tiene el conjunto forma un guión, por lo que $('#bar').data('foo-bar-baz')va a funcionar, pero $('#bar').data()['foo-bar-baz']no lo hará. Por esta razón, sugiero que las personas eviten usar la forma con guiones.
zzzzBov
1
ok, ahora entiendo lo que quieres decir. No sabía sobre ese pequeño detalle, gracias por la actualización :)
vitorbal
1
@SableFoste, ¿qué enlace? api.jquery.com/data es el enlace correcto para el método y no ha cambiado hasta donde yo sé.
zzzzBov
1
me gusta, foo, bar, baz, fizz, zumbido más: D
Usman Younas
1
Amo cada línea.
Foo Bar el
108

La principal diferencia entre los dos es dónde se almacena y cómo se accede.

$.fn.attr almacena la información directamente en el elemento en atributos que son visibles públicamente después de la inspección, y que también están disponibles en la API nativa del elemento.

$.fn.dataalmacena la información en un lugar ridículamente oscuro . Se encuentra en una variable local cerrada sobre llamada data_userque es una instancia de una función definida localmente Datos. Esta variable no es accesible desde fuera de jQuery directamente.

Conjunto de datos con attr()

  • accesible desde $(element).attr('data-name')
  • accesible desde element.getAttribute('data-name'),
  • si el valor estaba en forma de data-nametambién accesible desde $(element).data(name)y element.dataset['name']yelement.dataset.name
  • visible en el elemento tras la inspección
  • no pueden ser objetos

Conjunto de datos con .data()

  • accesible solo desde.data(name)
  • no accesible desde .attr()o desde cualquier otro lugar
  • no visible públicamente en el elemento tras la inspección
  • pueden ser objetos
Travis J
fuente
2
Sí, mi pregunta principal era dónde se almacenaban estos datos, ¡así que gracias por esa información!
Max Wilder
2
También .attr()es el camino a seguir, si luego desea utilizar los datos como selector ( .data()no se encontrará; consulte codepen.io/anon/pen/EvawPV?editors=1011 )
Kamafeather
1

Puede usar el data-*atributo para incrustar datos personalizados. Los data-*atributos nos permiten incorporar atributos de datos personalizados en todos los elementos HTML.

El .data()método jQuery le permite obtener / establecer datos de cualquier tipo en elementos DOM de una manera segura de referencias circulares y, por lo tanto, de pérdidas de memoria.

El .attr()método jQuery obtiene / establece el valor del atributo solo para el primer elemento del conjunto coincidente.

Ejemplo:

<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
fuente