原谅我没有更具体的这一点。我有这么奇怪的错误。加载文档后,我会循环一些最初有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,live
另外,来自链接的片段......
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>
答案 0 :(得分:183)
几天前,当我使用.data()
和.attr('data-name')
处理HTML5数据属性时,我遇到了类似的“错误”。
您描述的行为不是错误,而是设计原因。
.data()
调用很特殊 - 它不仅检索HTML5数据属性,还尝试评估/解析属性。因此,当通过data-myjson='{"hello":"world"}'
检索时,使用.data()
这样的属性将返回Object
,而通过.attr()
检索将返回一个字符串。 See jsfiddle example.
由于.data()
执行了额外的处理,jQuery将属性评估的结果存储在$.cache
中 - 毕竟,一旦评估了数据属性,在每个{{1}上重新评估将是浪费调用 - 特别是因为数据变量可以包含复杂的JSON字符串。
我说了以下所有内容:通过.data()
检索属性后,.data()
所做的任何更改都不会被后续.attr('data-myvar', '')
次调用看到。 Test this out on jsfiddle.
为避免此问题,不要混用.data()
和.data
来电。使用其中一个。
答案 1 :(得分:8)
这是误解的结果: 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")
数字元素上创建data-answer="42"
,而不是字符串,甚至将事物解析为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>
答案 2 :(得分:5)
那是因为属性的名称是data-itemname
。您不能以速记-
表示法使用obj.attribute
(obj.data-itemname将被解释为“obj.data minus itemname”)。
答案 3 :(得分:4)
为什么不在任何地方使用.data()
?
您也可以在HTML上声明内联的默认值,这也很好。
<span data-code="pony">text</span>
和
$("span").data("code") == "pony" // true
如果你想改变它,你只需要
$("span").data("code", "not-a-pony");
并完全删除它,你可以调用
$("span").removeData("code");
你应该尽量避免使用.attr("data-*")
,我不知道你为什么要这么做。
答案 4 :(得分:3)
.attr("data-itemname", "someValue")
修改DOM。
.data("itemname", "someValue")
修改jQuery缓存。
要在以下Javascript和CSS中使用此功能,必须同时设置两者。
theaterA.find(".someLink").attr("data-itemname", "someValue");
theaterA.find(".someLink").data("itemname", "someValue");
答案 5 :(得分:1)
您必须使用.data('itemname', 'someValue');
设置数据。使用.attr()
设置数据属性不起作用:http://jsfiddle.net/ThiefMaster/YHsKx/
但是,您可以使用例如提供内联值标记中的<div data-key="value">
。
答案 6 :(得分:0)
我看到这为如何处理数据属性设置带来了分歧。
我也遇到了这个问题,我发现问题似乎仅仅是数据属性名称格式。
以我的经验,您应该避免在数据变量(“ 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");
我希望它会有所帮助。 欢呼大家!