Perdóname por no ser más específico en esto. Tengo un error tan extraño. Después de que se carga el documento, hago un bucle con algunos elementos que originalmente tenían data-itemname=""
y configuro esos valores usando .attr("data-itemname", "someValue")
.
Problema: cuando luego recorro esos elementos, si lo hago elem.data().itemname
, obtengo ""
, pero si lo hago elem.attr("data-itemname")
, obtengo "someValue"
. Es como si el .data()
captador de jQuery solo obtiene elementos que están configurados inicialmente para contener algún valor, pero si originalmente están vacíos y luego configurados, entonces .data()
no obtiene el valor más adelante.
He intentado recrear este error, pero no he podido.
Editar
¡He recreado el error! http://jsbin.com/ihuhep/edit#javascript,html,live
Además, fragmentos del enlace anterior ...
JS:
var theaters = [
{ name: "theater A", theaterId: 5 },
{ name: "theater B", theaterId: 17 }
];
$("#theaters").html(
$("#theaterTmpl").render(theaters)
);
// DOES NOT WORK - .data("name", "val") does NOT set the val
var theaterA = $("[data-theaterid='5']");
theaterA.find(".someLink").data("tofilllater", "theater5link"); // this does NOT set data-tofilllater
$(".someLink[data-tofilllater='theater5link']").html("changed link text"); // never gets changed
// WORKS - .attr("data-name", "val") DOES set val
var theaterB = $("[data-theaterid='17']");
theaterB.find(".someLink").attr("data-tofilllater", "theater17link"); // this does set data-tofilllater
$(".someLink[data-tofilllater='theater17link']").html("changed link text");
HTML:
<body>
<div id="theaters"></div>
</body>
<script id="theaterTmpl" type="text/x-jquery-tmpl">
<div class="theater" data-theaterid="{{=theaterId}}">
<h2>{{=name}}</h2>
<a href="#" class="someLink" data-tofilllater="">need to change this text</a>
</div>
</script>
elem.data("itemname")
asíelem.data().itemname
?elem.data().itemname = somevalue;
lo tanto , no cambia los datos subyacentes)Respuestas:
Me encontré con un "error" similar hace unos días cuando trabajaba con
.data()
y.attr('data-name')
para atributos de datos HTML5.El comportamiento que está describiendo no es un error, sino por diseño.
La
.data()
llamada es especial: no solo recupera atributos de datos HTML5, sino que también intenta evaluar / analizar los atributos. Entonces, con un atributo comodata-myjson='{"hello":"world"}'
cuando se recupera a través de.data()
, devolverá unObject
tiempo de recuperación a través de.attr()
devolverá una cadena. Vea el ejemplo de jsfiddle.Dado
.data()
que el procesamiento adicional, jQuery almacena los resultados de la evaluación de atributos en$.cache
, después de todo, una vez que se ha evaluado un atributo de datos, sería un desperdicio volver a evaluar en cada.data()
llamada, especialmente porque las variables de datos pueden contener cadenas JSON complejas.Dije todo eso para decir lo siguiente: después de recuperar un atributo a través de
.data()
cualquier cambio realizado por.attr('data-myvar', '')
, no será visto por.data()
llamadas posteriores . Pruebe esto en jsfiddle.Para evitar este problema , no mezcle
.data
y.attr()
llame. Usar uno u otro.fuente
Este es el resultado de un malentendido:
data
NO es un descriptor de acceso paradata-*
atributos . Es más y menos que eso.data
es un acceso para la caché de datos de jQuery en el elemento. Esa caché se inicializa a partir de losdata-*
atributos si hay alguno presente, perodata
nunca escribe en los atributos, ni el cambio de atributo cambia la caché de datos después de la inicialización:data
también masajea lo que encuentra de varias maneras, adivinando tipos de datos, haciendodata("answer")
un elemento condata-answer="42"
un número, no una cadena, o incluso analizando cosas como JSON si se ven como JSON:Si desea usar los atributos (tanto leerlos como establecerlos), use
attr
, nodata
.attr
es un descriptor de acceso para atributos.fuente
Eso es porque el nombre del atributo es
data-itemname
. No se puede utilizar-
en laobj.attribute
notación abreviada (obj.data-itemname se interpretaría como "obj.data menos itemname").fuente
.attr("data-itemname", "someValue")
modifica el DOM..data("itemname", "someValue")
modifica la caché de jQuery.Para que esto funcione en el seguimiento de Javascript y, además, en CSS, debe configurar ambos.
fuente
¿Por qué no lo usas en
.data()
todas partes?También puede declarar valores predeterminados en línea en el HTML, lo cual también está bien.
y
si quieres cambiarlo solo hazlo
y para eliminarlo por completo, podría invocar
realmente deberías intentar evitar el uso
.attr("data-*")
, no sé por qué querrías hacerlo de todos modos.fuente
.attr('data-*', ...)
no hará que los datos sean visibles para.data()
getAttribute()
ysetAttribute()
, por lo que ambos métodos accederán a los atributos reales y volverá a funcionar. O simplemente usaría ladataSet
propiedad que proporcionan los navegadores modernos.class
lugar, ya que los navegadores tienen funciones nativas para obtener elementos con una determinada clase.Debe configurar los datos usando
.data('itemname', 'someValue');
. Usar.attr()
para establecer atributos de datos no funcionará: http://jsfiddle.net/ThiefMaster/YHsKx/Sin embargo, puede proporcionar valores en línea utilizando, por ejemplo,
<div data-key="value">
en el marcado.fuente
.data()
llamada establece el atributo, mientras que la.attr()
llamada no hace nada..attr()
en absoluto, solo.data()
, y la longitud del selector$(".someLink[data-tofilllater='theater5link']")
, es cero. así que es como si tuviera que usar.attr()
: /Puedo ver que esto ha generado cierta división sobre cómo abordar la configuración de atributos de datos.
Yo también me encontré con este problema y descubrí que el problema parecía ser simplemente el formato del nombre del atributo de datos .
En mi experiencia, debe evitar el uso de guiones en la variable de datos (el nombre de la variable que viene después de " datos- ").
Esto no funcionó para mí:
[Margen]
[jQuery]
¡Pero lo siguiente funcionó bien! :):
(Uso un guión bajo en lugar de un guión cuando es necesario)
[Margen]
[jQuery]
Espero que ayude. ¡Salud a todos!
fuente