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

时间:2012-01-03 02:14:34

标签: jquery

原谅我没有更具体的这一点。我有这么奇怪的错误。加载文档后,我会循环一些最初有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>

7 个答案:

答案 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>

如果您想使用属性(阅读和设置属性),请使用attr,而不是dataattr 是属性的访问者。

答案 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");

我希望它会有所帮助。 欢呼大家!