jQuery.data()不起作用,但.attr()起作用



请原谅我没有更具体地说明这一点。我有一个奇怪的虫子。加载文档后,我循环一些最初具有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,而不是dataattr属性的访问器。

.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");

我希望它能有所帮助。为大家干杯!

最新更新