请原谅我没有更具体地说明这一点。我有一个奇怪的虫子。加载文档后,我循环一些最初具有data-itemname=""
的元素,并使用.attr("data-itemname", "someValue")
设置这些值。
问题:当我稍后循环这些元素时,如果我执行elem.data().itemname
,我会得到""
,但如果执行elem.attr("data-itemname")
,我会获得"someValue"
。这就像jQuery的.data()
getter只获取最初设置为包含某个值的元素,但如果它们最初是空的,后来又被设置,那么.data()
以后就不会获取值
我一直在尝试重新创建这个错误,但一直未能成功。
编辑
我已经重新创建了bug!http://jsbin.com/ihuhep/edit#javascript,html,实时
此外,上面链接的片段。。。
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>
几天前,我在使用.data()
和.attr('data-name')
处理HTML5数据属性时遇到了类似的"bug"。
您所描述的行为不是bug,而是经过设计的。
.data()
调用是特殊的——它不仅检索HTML5数据属性,还尝试评估/解析这些属性。因此,当通过.data()
检索时,具有类似data-myjson='{"hello":"world"}'
的属性将返回Object
,而通过.attr()
检索将返回字符串。请参阅jsfiddle示例。
由于.data()
进行额外的处理,jQuery将属性评估的结果存储在$.cache
中——毕竟,一旦评估了数据属性,那么在每次.data()
调用上重新评估将是浪费的——尤其是因为数据变量可能包含复杂的JSON字符串。
我说了这么多,意思是:通过.data()
检索属性后,.attr('data-myvar', '')
所做的任何更改都不会被后续的.data()
调用所看到在jsfiddle上测试一下。
若要避免此问题,请不要混用.data
和.attr()
调用使用其中一个。
这是误解的结果:data
不是data-*
属性的访问器。比这还要多也要少。
data
是元素上jQuery数据缓存的访问器。该缓存是从data-*
属性初始化的(如果存在),但data
从不向属性写入,初始化后更改属性也不会更改数据缓存:
const div = $("[data-example]");
console.log('div.data("example"):', div.data("example"));
console.log('div.attr("data-example"):', div.attr("data-example"));
console.log('Using div.data("example", "updated")');
div.data("example", "updated");
console.log('div.data("example"):', div.data("example"));
console.log('div.attr("data-example"):', div.attr("data-example"));
<div data-example="initial value"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
data
还以各种方式处理它所发现的内容,猜测数据类型,使data-answer="42"
元素上的data("answer")
为数字,而不是字符串,甚至如果它们看起来像JSON,则将其解析为JSON:
console.log(typeof $("[data-answer]").data("answer"));
console.log(typeof $("[data-json]").data("json"));
console.log(typeof $("[data-str]").data("str"));
<div data-answer="42"></div>
<div data-json='{"answer":42}'></div>
<div data-str="example"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
如果要使用属性(读取和设置属性),请使用attr
,而不是data
。attr
是属性的访问器。
.attr("data-itemname", "someValue")
修改DOM。
.data("itemname", "someValue")
修改jQuery缓存。
要在下面的Javascript和CSS中实现这一点,您必须同时设置两者。
theaterA.find(".someLink").attr("data-itemname", "someValue");
theaterA.find(".someLink").data("itemname", "someValue");
data-itemname
。不能在缩写obj.attribute
表示法中使用-
(obj.data-itemname将被理解为"obj.data减去itemname")。
为什么不在任何地方都使用.data()
?
您还可以在HTML上内联声明默认值,这也很好。
<span data-code="pony">text</span>
和
$("span").data("code") == "pony" // true
如果你想改变它,你只需要做
$("span").data("code", "not-a-pony");
要完全删除它,您可以调用
$("span").removeData("code");
你真的应该尽量避免使用.attr("data-*")
,我不知道你为什么要这么做。
必须使用.data('itemname', 'someValue');
设置数据。使用.attr()
设置数据属性将不起作用:http://jsfiddle.net/ThiefMaster/YHsKx/
但是,可以通过在标记中使用例如<div data-key="value">
来提供内联值。
我可以看到,这在如何处理数据属性设置方面带来了一些分歧。
我也遇到了这个问题,我发现问题似乎只是数据属性名称格式化。
根据我的经验,您应该避免在数据变量中使用连字符("data-"之后的变量名)。
这对我不起作用:
[标记]
<div class="list" id="myElement1" data-item-order="some-value"> .... </div>
[jQuery]
jQuery("#myElement1").data("item-order", "my-new-value");
但以下操作很好!:):
(需要时我使用下划线而不是连字符)
[标记]
<div class="list" id="myElement1" data-item_order="some-value"> .... </div>
[jQuery]
jQuery("#myElement1").data("item_order", "my-new-value");
我希望它能有所帮助。为大家干杯!