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


107

请原谅我没有对此做更多具体说明。我有一个奇怪的错误。在文档加载后,我循环了一些原来具有的元素data-itemname="",并使用设置了这些值.attr("data-itemname", "someValue")

问题:当我以后遍历那些元素时,如果elem.data().itemname我知道"",则得到,但如果我知道,则elem.attr("data-itemname")得到"someValue"。就像jQuery的.data()getter只获取最初设置为包含某些值的元素,但是如果它们最初为空,然后又被设置,则以后.data()不会获取该值。

我一直在尝试重新创建此错误,但未能成功。

编辑

我已经重新创建了错误!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>

4
尽力重建错误:-)
dkamins 2012年

1
elem.data("itemname")不是elem.data().itemname
霍根2012年

而elem.data()。itemname将让您读取值,而不会让您设置值。(因此elem.data().itemname = somevalue;,不会更改基础数据。)
Hogan 2012年

@dkamins-我已经重新创建了该错误,请查看编辑后的版本。
伊恩·戴维斯

Answers:


210

几天前,在使用HTML5数据属性.data().attr('data-name')使用HTML5数据属性时,我遇到了类似的“错误” 。

您描述的行为不是错误,而是设计使然。

.data()调用非常特殊-它不仅会检索HTML5数据属性,而且还会尝试评估/解析这些属性。因此,与像一个属性data-myjson='{"hello":"world"}'当通过检索.data()将返回Object,同时通过检索.attr()将返回一个字符串。请参阅jsfiddle示例。

由于.data()jQuery会进行额外的处理,因此将属性评估的结果存储在其中$.cache-毕竟,一旦评估了数据属性,则在每次.data()调用时重新评估都是浪费的-特别是因为数据变量可以包含复杂的JSON字符串。

我说的全部是以下内容:通过进行.data()任何更改检索属性后.attr('data-myvar', ''),后续.data()调用将看不到。 在jsfiddle上进行测试。

为避免此问题,请勿混用.data.attr()通话。使用一个或另一个。


将此标记为答案。请查看该测试有关.data()与.attr()的所有可能情况的信息,其中包括使用每种方法进行&设置,以及在设置选择器之后输出选择器的长度,jsbin.com/acegef/edit# javascript,html,live
Ian Davis'1

9
至少这可以解释显然是非直觉的行为……尽管当使用第三方库时,这可能会引起一些较小的麻烦,其中一些仅使用data(),而其他更改实际属性。
Haroldo_OK 2013年

1
@leepowers,“如果确实通过缓存( $ .cache),那么似乎没有好处!而不是盲目地依赖缓存,后续的.data()调用可以执行一些基本的check(),例如值是否现在为空或字符串长度是否已更改(将缓存与当前值匹配)
minhajul 2015年

1
应该注意的是,如果没有更早检索到该值,则尝试设置data('id',val)也会失败... Jquery对data()函数的出色设计。
andreszs

3
因此,正是data()高速缓存让我难忘了几个小时。难怪为什么无论我更改其值多少,它仍然返回相同的值。谢谢你
Lynnell Emmanuel Neri

17

这是误解的结果: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 属性的访问器。


6

这是因为属性的名称是data-itemname。您不能使用-简写形式obj.attribute(obj.data-itemname将被解释为“ obj.data减去itemname”)。


谁说的?你能提供一个链接吗?
jahrichie 2015年

6

.attr("data-itemname", "someValue") 修改DOM。

.data("itemname", "someValue") 修改jQuery缓存。

要使此功能在以下Javascript中以及CSS中起作用,您必须同时设置两者。

theaterA.find(".someLink").attr("data-itemname", "someValue");
theaterA.find(".someLink").data("itemname", "someValue");

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-*"),但我不知道您为什么仍要这样做。


s /应该/必须,使用.attr('data-*', ...)不会使数据可见.data()
ThiefMaster 2012年

但是,用attr()来实现它不是您在没有 jQuery时必须要做的方式吗?(带有getAttribute tho)
powerbuoy 2012年

如果您没有jQuery,请使用getAttribute()setAttribute()-,因此这两种方法都将访问实际属性,并且将再次起作用。或者,您仅使用dataSet现代浏览器提供的属性。
ThiefMaster 2012年

1
不要选择那样的元素。由于它必须遍历文档中的每个单个元素,因此效率极低。class由于浏览器具有本机函数来获取具有特定类的元素,请改用。
ThiefMaster 2012年

1
但是,“ 555”是数据,因此我应该使用data()逻辑。将数据放在类名中是将数据与表示形式混合在一起。我想这是另一种方式。
伊恩·戴维斯

1

您必须使用设置数据.data('itemname', 'someValue');。使用.attr()到的数据集的属性将无法正常工作:http://jsfiddle.net/ThiefMaster/YHsKx/

但是,您可以通过<div data-key="value">在标记中使用例如提供内联值。


在jsfiddle中,完成两个设置后,get即可工作。因此,做attr(“ data-itemname”,“ value”)确实有效。我正在使用Chrome。
伊恩·戴维斯

@Ian呃,不。在.data()调用设置属性,而.attr()调用不起任何作用。
bevacqua 2012年

@IanDavis:单击“设置属性”,然后单击“获取”将为您提供一个空对象。仅“设置数据”有效。
ThiefMaster 2012年

@Nico-这正是我所做的:(1)单击“设置属性”按钮,然后(2)单击“获取”按钮。这就是发生的情况:它使我感到震惊,“ {{test”:“喵”}}”。因此,.attr()设置属性。否则,警报将为空。如果按照这些确切步骤进行操作,会得到不同的结果吗?谢谢。
伊恩·戴维斯

1
@ThiefMaster -在theaterA在我提供的代码,我没有使用.attr()在所有的,只是.data(),和选择的长度,$(".someLink[data-tofilllater='theater5link']")是零。所以就像我必须使用.attr():/
Ian Davis'1

0

我可以看到,这为如何处理数据属性设置带来了分歧。

我也遇到了这个问题,发现问题似乎仅仅是数据属性名称格式

以我的经验,您应该避免在data变量(“ 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");

希望对您有所帮助。欢呼大家!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.