Perdoe-me por não ser mais específico sobre isso. Eu tenho um bug tão estranho. Depois que o documento é carregado, faço um loop em alguns elementos que originalmente o continham data-itemname=""
e defino esses valores usando .attr("data-itemname", "someValue")
.
Problema: Quando mais tarde faço um loop através desses elementos, se eu faço elem.data().itemname
, eu entendo ""
, mas se eu faço elem.attr("data-itemname")
, eu entendo "someValue"
. É como se o .data()
getter do jQuery apenas obtivesse os elementos que são configurados inicialmente para conter algum valor, mas se eles estiverem originalmente vazios e posteriormente configurados, .data()
não obterá o valor posteriormente.
Tenho tentado recriar esse bug, mas não consegui.
Editar
Eu recriei o bug! http://jsbin.com/ihuhep/edit#javascript,html,live
Além disso, trechos do link acima ...
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")
nãoelem.data().itemname
?elem.data().itemname = somevalue;
, não altera os dados subjacentes.)Respostas:
Encontrei um "bug" semelhante há alguns dias ao trabalhar com
.data()
e.attr('data-name')
para atributos de dados HTML5.O comportamento que você está descrevendo não é um bug, mas é intencional.
A
.data()
chamada é especial - ela não apenas recupera atributos de dados HTML5, mas também tenta avaliar / analisar os atributos. Portanto, com um atributo comodata-myjson='{"hello":"world"}'
when recuperado via.data()
retornará umObject
while recuperação via.attr()
retornará uma string. Veja o exemplo de jsfiddle.Uma vez que
.data()
faz o processamento extra, o jQuery armazena os resultados da avaliação de atributos$.cache
- afinal, uma vez que um atributo de dados foi avaliado, seria um desperdício reavaliar em cada.data()
chamada - especialmente porque as variáveis de dados podem conter strings JSON complexas.Eu disse tudo isso para dizer o seguinte: Depois de recuperar um atributo por meio de
.data()
quaisquer alterações feitas por.attr('data-myvar', '')
, não será visto pelas.data()
chamadas subsequentes . Teste isso no jsfiddle.Para evitar este problema , não misture
.data
e faça.attr()
chamadas. Use um ou outro.fonte
Este é o resultado de um mal-entendido:
data
NÃO é um acessador dedata-*
atributos . É mais e menos do que isso.data
é um acessador para o cache de dados do jQuery no elemento. Esse cache é inicializado a partir dedata-*
atributos, se houver algum presente, masdata
nunca grava nos atributos, nem a alteração do atributo altera o cache de dados após a inicialização:data
também massageia o que encontra de várias maneiras, adivinhando os tipos de dados, criandodata("answer")
em um elemento comdata-answer="42"
um número, não uma string, ou até mesmo analisando coisas como JSON se forem semelhantes a JSON:Se você quiser usar os atributos (tanto lendo quanto configurando-os), use
attr
, nãodata
.attr
é um acessador para atributos.fonte
Isso porque o nome do atributo é
data-itemname
. Você não pode usar-
naobj.attribute
notação abreviada (obj.data-itemname seria interpretado como "obj.data menos itemname").fonte
.attr("data-itemname", "someValue")
modifica o DOM..data("itemname", "someValue")
modifica o cache jQuery.Para fazer isso funcionar seguindo Javascript e, além disso, CSS, você deve definir ambos.
fonte
Por que você não usa em
.data()
qualquer lugar?Você também pode declarar valores padrão embutidos no HTML, o que também é bom.
e
se você quiser mudar, basta fazer
e para removê-lo completamente, você pode invocar
você realmente deve tentar evitar o uso
.attr("data-*")
, não sei por que você gostaria de fazer isso de qualquer maneira.fonte
.attr('data-*', ...)
não tornará os dados visíveis para.data()
getAttribute()
esetAttribute()
- então os dois métodos acessarão os atributos reais e funcionarão novamente. Ou você apenas usaria adataSet
propriedade que os navegadores modernos fornecem.class
Em vez disso, use um, pois os navegadores têm funções nativas para obter elementos com uma determinada classe.Você deve definir os dados usando
.data('itemname', 'someValue');
. Usar.attr()
para definir atributos de dados não funciona: http://jsfiddle.net/ThiefMaster/YHsKx/No entanto, você pode fornecer valores embutidos usando, por exemplo,
<div data-key="value">
na marcação.fonte
.data()
chamada define o atributo, enquanto a.attr()
chamada não faz nada..attr()
nada, apenas.data()
, e, o comprimento do seletor ,,$(".someLink[data-tofilllater='theater5link']")
é zero. então é como se eu tivesse que usar.attr()
: /Posso ver que isso trouxe algumas divisões sobre como abordar a configuração do atributo de dados.
Eu também tive esse problema e descobri que o problema parecia ser simplesmente a formatação do nome do atributo de dados .
Na minha experiência, você deve evitar o uso de hifens na variável de dados (o nome da variável que vem depois de " data- ").
Isso não funcionou para mim:
[Markup]
[jQuery]
Mas o seguinte funcionou muito bem! :):
(Eu uso um sublinhado em vez de um hífen quando necessário)
[Markup]
[jQuery]
Espero que ajude. Felicidades a todos!
fonte