jQuery .data () çalışmıyor, ancak .attr () çalışıyor


107

Bu konuda daha spesifik olmadığım için beni affet. Çok garip bir böceğim var. Doküman yüklendikten sonra, orijinal olarak sahip olan bazı öğeleri döngüye data-itemname=""alıyorum ve bu değerleri kullanarak ayarlıyorum .attr("data-itemname", "someValue").

Sorun: Daha sonra bu öğeler arasında döngü gerçekleştirdiğimde, yaparsam elem.data().itemname, alırım "", ancak yaparsam elem.attr("data-itemname"), alırım "someValue". Tıpkı jQuery'nin .data()alıcısının yalnızca başlangıçta bir değer içerecek şekilde ayarlanan öğeleri alması gibi, ancak bunlar başlangıçta boşsa ve daha sonra ayarlanmışsa, .data()değeri daha sonra alamaz.

Bu hatayı yeniden oluşturmaya çalışıyorum ama yapamadım.

Düzenle

Böceği yeniden yarattım! http://jsbin.com/ihuhep/edit#javascript,html,live

Ayrıca, yukarıdaki bağlantıdan pasajlar ...

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

1
Öyle değil mi elem.data("itemname")değil elem.data().itemname?
Hogan

elem.data (). itemname ise değeri okumanıza izin verirken, değeri ayarlamanıza İZİN VERMEZ. (Böylece elem.data().itemname = somevalue;temeldeki verileri değiştirmez.)
Hogan

@dkamins - Hatayı yeniden oluşturdum, lütfen düzenlenmiş sürüme bakın.
Ian Davis

Yanıtlar:


210

İle çalışırken Birkaç gün önce benzer bir "hata" koştu .data()ve .attr('data-name')HTML5 veri özellikleri için.

Tanımladığınız davranış bir hata değil, tasarım gereğidir.

.data()Çağrı özeldir - sadece HTML5 veri almak vermez aynı zamanda / değerlendirmek özelliklerini ayrıştırmak için girişimlerini bağlıyor. Dolayısıyla, data-myjson='{"hello":"world"}'aracılığıyla alındığında gibi bir öznitelikle .data(), bir Objectsüre alma işlemi .attr()bir dizge döndürür. Jsfiddle örneğine bakın.

Yana .data()ekstra işleme jQuery depolar nitelik değerlendirme sonuçlarını yapar içinde $.cache- sonuçta bir veri niteliği değerlendirilmiştir kez karşı savurgan olurdu her üzerine yeniden değerlendirmek .data()çağrısı - veri değişkenleri karmaşık JSON dizeleri içerebilir özellikle.

Aşağıdakileri söylemek için hepsini söyledim: Bir özniteliği aldıktan sonra .data(), tarafından yapılan herhangi bir değişiklik .attr('data-myvar', '')sonraki .data()çağrılarda görülmeyecektir . Bunu jsfiddle'da test edin.

Bu sorunu önlemek için karıştırmayın .datave aramayın .attr(). Birini veya diğerini kullanın.


bunu cevap olarak işaretlemek. lütfen bu teste bakın .data () ile .attr () karşılaştırması, her birini alma ve ayarlama ve seçiciler ayarlandıktan sonra uzunluklarının çıktısını alma dahil, jsbin.com/acegef/edit# javascript, html, canlı
Ian Davis

9
En azından bu, görünüşte sezgisel olmayan davranışı açıklıyor ... ancak bu, üçüncü taraf kitaplıkları kullanırken, bazıları yalnızca verileri () kullanırken ve diğerleri gerçek özniteliği değiştirirken bazı küçük baş ağrılarına neden olabilir.
Haroldo_OK

1
@leepowers, ".data () aracılığıyla bir özniteliği aldıktan sonra .attr ('data-myvar', '') tarafından yapılan herhangi bir değişiklik, sonraki .data () çağrılarında görülmeyecektir" $ .cache), o zaman hiç iyi görünmüyor! Önbelleğe körü körüne güvenmek yerine, sonraki .data () çağrıları, değerin şimdi boş olup olmadığı veya dize uzunluğunun değişip değişmediği (önbelleği mevcut değerle eşleştirerek) gibi bazı temel kontroller () yapabilir
minhajul

1
Verileri ('id', val) ayarlamaya çalışmanın, değer daha önce alınmamışsa da başarısız olduğuna dikkat edilmelidir ... data () işlevinin Jquery tarafından mükemmel tasarımı.
andresz

3
Yani beni saatlerce tutan veri () önbelleği. Neden değerini ne kadar değiştirirsem değiştireyim, yine de aynı değeri döndürdüğüne şaşmamalı. Bunun için teşekkürler.
Lynnell Emmanuel Neri

17

Bu bir yanlış anlaşılmanın sonucudur: öznitelikler dataiçin erişimci DEĞİLDİRdata-* . Hem daha çok hem de daha az.

datajQuery'nin öğe üzerindeki veri önbelleği için bir erişimcidir. Bu önbellek edilir başlatıldı gelen data-*orada herhangi birinin varlığında, ancak eğer nitelikler dataasla yazıyor özelliklerine, ne de başlatmasından sonra nitelik değiştireceğim veri önbelleği değişen yapar:

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>

dataayrıca bulduğu şeyi çeşitli şekillerde masaj yapar, veri türlerini tahmin eder, bir sayı data("answer")ile bir öğe üzerinde data-answer="42", bir dizeyle değil, hatta JSON gibi görünüyorsa JSON olarak ayrıştırır:

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>

Öznitelikleri kullanmak istiyorsanız (hem okumak hem de ayarlamak), kullanın attr, değil data. attr olduğu özellikler için bir erişimci.


6

Çünkü özniteliğin adı data-itemname. Sen kullanamaz -steno içinde obj.attributegösterimde (obj.data-itemname "itemname obj.data eksi" şekilde yorumlanır olacaktır).


kim söylüyor? bir bağlantı verebilir misin
jahrichie

6

.attr("data-itemname", "someValue") DOM'u değiştirir.

.data("itemname", "someValue") jQuery önbelleğini değiştirir.

Bunun Javascript'i takip ederek çalışmasını sağlamak için CSS'ye ek olarak her ikisini de ayarlamanız gerekir.

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

4

Neden .data()her yerde kullanmıyorsun ?

Ayrıca varsayılan değerleri HTML üzerinde satır içi olarak bildirebilirsiniz, bu da bir sorun değildir.

<span data-code="pony">text</span>

ve

$("span").data("code") == "pony" // true

eğer değiştirmek istiyorsan sadece yap

$("span").data("code", "not-a-pony");

ve onu tamamen kaldırmak için çağırabilirsiniz

$("span").removeData("code");

gerçekten denemeli ve kullanmaktan kaçınmalısın .attr("data-*"), neden bunu yapmak istediğini bilmiyorum zaten.


s / should / must, kullanmak .attr('data-*', ...)veriyi görünür .data()
yapmaz

Ancak bunu jQuery olmadan yapmak zorunda olduğunuz şekilde attr () ile yapmak değil mi? (getAttribute tho ile)
powerbuoy

Kullandığınız jQuery'niz yoksa getAttribute()ve setAttribute()- bu nedenle her iki yöntem de gerçek özniteliklere erişecek ve yeniden çalışacaktır. Veya sadece dataSetmodern tarayıcıların sağladığı özelliği kullanırsınız .
ThiefMaster

1
Böyle öğeler seçmeyin. Belgedeki her bir öğe üzerinde yineleme yapması gerekeceğinden, korkunç derecede verimsizdir . classTarayıcıların belirli bir sınıfa sahip öğeleri almak için yerel işlevleri olduğundan bunun yerine a kullanın.
ThiefMaster

1
ancak "555" veridir, bu yüzden data () mantığını kullanmalıyım. bu verileri sınıf adına koymak, verileri sunumla karıştırmaktır. sanırım bunu yapmanın farklı bir yolu.
Ian Davis

1

Verileri kullanarak ayarlamalısınız .data('itemname', 'someValue');. .attr()Veri özniteliklerini ayarlamak için kullanmak işe yaramaz: http://jsfiddle.net/ThiefMaster/YHsKx/

Ancak, olabilir örneğin kullanarak satır içi değerler sağlamak <div data-key="value">işaretlemesinde.


jsfiddle'da, her iki seti de yaptıktan sonra get çalışır. yani, attr ("veri-öğe adı", "değer") yapmak İŞE ÇALIŞIR. Chrome kullanıyorum.
Ian Davis

@Ian uh, hayır. .data()ederken çağrı, niteliğini belirler .attr()çağrı hiçbir şey yapmaz.
bevacqua

@IanDavis: "set attr" e tıklayın ve "get" size boş bir nesne verecektir. Yalnızca "verileri ayarla" çalışır.
ThiefMaster

@Nico - tam olarak bunu yaptım: (1) "attr ayarla" düğmesini tıklayın, sonra (2) "al" düğmesini tıklayın. olan buydu: beni uyardı, "{" test ":" miyav "}". böylece, .attr () özniteliği ayarlar. aksi takdirde uyarı boş olurdu. Tam olarak bu adımları izlerseniz, farklı sonuçlar alıyor musunuz? Teşekkürler.
Ian Davis

1
@ThiefMaster - tiyatrodaA sağlanan kodumda hiç kullanmıyorum .attr(), sadece .data()ve seçicinin uzunluğu $(".someLink[data-tofilllater='theater5link']")sıfır. yani kullanmak zorunda olduğum gibi .attr(): /
Ian Davis

0

Bunun, veri özniteliği ayarına nasıl yaklaşılacağı konusunda bazı bölünmeler ortaya çıkardığını görebiliyorum.

Ben de bu sorunla karşılaştım ve sorunun sadece veri özniteliği adı biçimlendirmesi gibi göründüğünü gördüm .

Tecrübelerime göre, veri değişkeninde (" data- " dan sonra gelen değişken adı) tire kullanmaktan kaçınmalısınız .

Bu benim için işe yaramadı:

[İşaretleme]

<div class="list" id="myElement1" data-item-order="some-value"> .... </div>

[jQuery]

jQuery("#myElement1").data("item-order", "my-new-value");

Ancak aşağıdakiler gayet iyi çalıştı! :):

(Gerektiğinde kısa çizgi yerine alt çizgi kullanıyorum)

[İşaretleme]

<div class="list" id="myElement1" data-item_order="some-value"> .... </div>

[jQuery]

jQuery("#myElement1").data("item_order", "my-new-value");

Umut ediyorum bu yardım eder. Herkese şerefe!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.