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

Ian*_*vis 98 jquery

原谅我没有更具体的这一点.我有这么奇怪的错误.在doc加载之后,我循环了一些原来的元素data-itemname="",并使用它来设置这些值.attr("data-itemname", "someValue").

问题:当我后来循环通过这些元素时,如果我这样做elem.data().itemname,我会得到"",但如果我这样做elem.attr("data-itemname"),我会得到"someValue".这就像jQuery的.data()getter只获取最初设置为包含某些值的元素,但如果它们最初是空的,稍后设置,则稍后.data()不会获取该值.

我一直试图重新创建这个bug,但一直没能.

编辑

我重新创建了这个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");
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

lee*_*ers 189

几天前,当我使用.data().attr('data-name')处理HTML5数据属性时,我遇到了类似的"bug" .

您描述的行为不是错误,而是设计.

.data()调用是特殊的 - 它不仅检索HTML5数据属性,还尝试评估/解析属性.因此,使用像data-myjson='{"hello":"world"}'检索到的属性.data()将返回一段Object时间检索通过.attr()将返回一个字符串.参见jsfiddle示例.

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

我说了以下所有内容:通过后续调用后不会看到的任何更改检索属性后..data().attr('data-myvar', '').data() 在jsfiddle上测试一下.

为了避免这个问题,请不要混合.data.attr()调用.使用其中一个.

  • 至少这解释了明显不直观的行为......虽然当一个人使用第三方库时,这可能会导致一些较小的麻烦,其中一些只使用data(),另一些则改变实际属性. (8认同)
  • 所以,是 data() 缓存让我呆了几个小时。难怪无论我如何改变它的值,它仍然返回相同的值。谢谢你。 (3认同)

T.J*_*der 10

这是误解的结果:data不是data-*属性的访问者.它的数量越来越少.

data是元素上jQuery数据缓存的访问器.如果存在任何存在,则从属性初始化该缓存data-*,但从data写入属性,更改属性也不会在初始化后更改数据缓存.

data还可以通过各种方式对其发现的内容进行按摩,猜测数据类型,data("answer")使用data-answer="42"数字创建元素,而不是字符串,或者如果它们看起来正确,则将事物解析为JSON:

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"));
Run Code Online (Sandbox Code Playgroud)
<div data-example="initial value"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

如果要使用属性(读取和设置它们),请使用attr,而不是data.attr 属性的访问者.


小智 8

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

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

要使其在以下 Javascript 和 CSS 中工作,您必须同时设置两者。

theaterA.find(".someLink").attr("data-itemname", "someValue");
theaterA.find(".someLink").data("itemname", "someValue");
Run Code Online (Sandbox Code Playgroud)


Mar*_*c B 5

那是因为属性的名字是data-itemname.您不能使用-简写obj.attribute表示法(obj.data-itemname将被解释为"obj.data minus itemname").