jQuery .data()は機能しませんが、.attr()は機能します


107

これについてより具体的ではないことを許してください。私はそのような奇妙なバグを抱えています。ドキュメントが読み込まれた後、最初にがあった要素をループし、をdata-itemname=""使用してそれらの値を設定し.attr("data-itemname", "someValue")ます。

問題:後でこれらの要素をループするときに、を実行するelem.data().itemnameとが取得されます""が、を実行するelem.attr("data-itemname")とが取得され"someValue"ます。これは、jQueryの.data()ゲッターが、最初は値を含むように設定された要素のみを取得するようなものですが、それらが元々空で、後で設定され.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

1
そうではありませんelem.data("itemname")ではありませんかelem.data().itemname
ホーガン

elem.data()。itemnameでは値を読み取ることができますが、値を設定することはできません。(したがってelem.data().itemname = somevalue;、基礎となるデータは変更されません。)
Hogan

@dkamins-バグを再現しました。編集されたバージョンをご覧ください。
Ian Davis

回答:


210

で作業するとき、私は数日前に同様の「バグ」に走った.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
イアンデイビス

9
少なくともこれは明らかに非直感的な動作を説明します...しかし、サードパーティのライブラリを使用している場合、いくつかの小さな頭痛を引き起こす可能性があります。data()のみを使用しているものもあれば、実際の属性を変更しているものもあります。
Haroldo_OK 2013年

1
@leepowers、「。data()を介して属性を取得した後、.attr( 'data-myvar'、 '')によって行われた変更は、それが本当にcache( $ .cache)、それからそれは良くないようです!盲目的にキャッシュに依存する代わりに、後続の.data()呼び出しは、値が現在空か、文字列の長さが変更されたか(キャッシュを現在の値と一致させるか)などの基本的なチェックを実行できます
minhajul

1
data( 'id'、val)を設定しようとすると、値が以前に取得されなかった場合も失敗することに注意してください... Jqueryによるdata()関数の優れた設計。
andreszs 2017

3
したがって、何時間も私を保持しているのはdata()キャッシュです。値をどれほど変更しても、同じ値が返されるのは不思議ではありません。これをありがとう。
Lynnell Emmanuel Neri、2018

17

これは誤解の結果ですdatadata-*属性のアクセサーではありません。それは多かれ少なかれ両方です。

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

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 / should / must、使用し.attr('data-*', ...)てもデータが表示されない.data()
ThiefMaster

しかし、attr()を使用して jQueryを使用せずに実行する必要があるのではないでしょうか?(getAttribute thoを使用)
powerbuoy 2012年

jQueryがない場合は、 getAttribute() andsetAttribute()ので、両方のメソッドが実際の属性にアクセスし、再び機能します。または、dataSet最新のブラウザが提供するプロパティを使用するだけです。
ThiefMaster、2012年

1
そのような要素を選択しないでください。ドキュメント内のすべての要素を反復処理する必要があるため、ひどく非効率的です。使うclassブラウザには特定のクラスの要素を取得するネイティブ関数があるため代わりにを。
ThiefMaster、2012年

1
しかし、「555」はデータなので、data()ロジックを使用する必要があります。そのデータをクラス名に入れることは、データをプレゼンテーションと混合することです。私はそれを行う別の方法だと思います。
Ian Davis

1

を使用してデータを設定する必要があります.data('itemname', 'someValue');。を使用.attr()してデータ属性を設定することはできません:http : //jsfiddle.net/ThiefMaster/YHsKx/

ただし、たとえばマークアップで使用することにより、インライン値提供できます<div data-key="value">


jsfiddleでは、両方のセットを実行した後にgetが機能します。したがって、attr( "data-itemname"、 "value")を実行しても機能します。Chromeを使用しています。
Ian Davis

@イアンええ、いいえ。.data()一方、コールは、属性を設定し.attr()、コールは何もしません。
bevacqua 2012年

@IanDavis:「属性設定」をクリックすると、「取得」すると空のオブジェクトが表示されます。「データの設定」のみが機能します。
ThiefMaster、2012年

@Nico-これはまさに私がやったことです:(1)「set attr」ボタンをクリックしてから、(2)「get」ボタンをクリックします。これが起こったことです:「{"test": "meow"}」と私に警告しました。したがって、.attr()は属性を設定します。それ以外の場合、アラートは空でした。これらの正確な手順に従うと、異なる結果が得られますか?ありがとう。
Ian Davis

1
@ThiefMaster-提供されたコードのtheatreAで、私はまったく使用.attr()していません。.data()セレクターの長さ$(".someLink[data-tofilllater='theater5link']")はゼロです。だから私は使用しなければならないよう.attr()です:/
Ian Davis

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

お役に立てば幸いです。みんな乾杯!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.