jQuery Data()APIを使用してデータ属性を設定できません


131

MVCビューに次のフィールドがあります。

@Html.TextBoxFor(model => model.Course.Title, new { data_helptext = "Old Text" })</span>

別のjsファイルで、data-helptext属性を文字列値に設定します。これが私のコードです:

alert($(targetField).data("helptext"));

$(targetField).data("helptext", "Testing 123");

alert()呼び出しは、それが警告ダイアログのテキスト「古いテキスト」を示し、正常に動作します。ただし、data-helptext属性を "Testing 123" に設定する呼び出しは機能しません。「古いテキスト」は、属性の現在の値のままです。

data()の呼び出しを誤って使用していますか?これをウェブで調べたところ、何が悪いのかわかりません。

HTMLマークアップは次のとおりです。

<input data-helptext="Old Text" id="Course_Title" name="Course.Title" type="text" value="" />

コードは問題ありません。このデモでは問題ありません。どのバージョンのjQueryを使用していますか?
andyb

ASP NET MVCプロジェクトテンプレートに付属している1.5.1を使用しています。jQueryを更新する必要があるのでしょうか?
Jason Evans

OK、それはjQueryのバージョンではありません。本当に古いバージョンかもしれないと思っていました。使用しているdata()APIは、v1.2.3で追加されました
andyb

マークアップを追加していただけませんか?カスタムHTML5 data-属性を使用していますか?
andyb

どのように価値を観察していますか?jQueryは値をDOMに永続化しませんが、正しく更新します。テストと説明については、以下の私の答えを参照してください
andyb '26 / 07/26

回答:


239

ドキュメントに記載されて.data()いる

data-属性は、最初にdataプロパティにアクセスしたときにプルされ、その後はアクセスまたは変更されません(すべてのデータ値はjQueryに内部的に保存されます)。

これは、jQueryの$ .fn.data()を変更すると、対応するhtml 5 data- *属性が更新されない理由についても説明しました

以下の私の元の答えのデモはもう機能していないようです。

回答を更新しました

もう一度、ドキュメントから.data()

ダッシュが埋め込まれた属性の扱いは、jQuery 1.6で変更され、W3C HTML5仕様に準拠しました。

したがって<div data-role="page"></div>、次のことが当てはまります$('div').data('role') === 'page'

私は$('div').data('data-role')それが過去にうまくいったと確信していますが、それはもはやそうではないようです。コンソールを開く必要がなく、HTMLにログを記録するより優れたショーケースを作成し、マルチハイフンからキャメルケースのデータ属性変換の追加例を追加しました。

更新されたデモ(2015-07-25)

jQuery Data vs Attrも参照してください

HTML

<div id="changeMe" data-key="luke" data-another-key="vader"></div>
<a href="#" id="changeData"></a>
<table id="log">
    <tr><th>Setter</th><th>Getter</th><th>Result of calling getter</th><th>Notes</th></tr>
</table>

JavaScript(jQuery 1.6.2+)

var $changeMe = $('#changeMe');
var $log = $('#log');

var logger;
(logger = function(setter, getter, note) {
    note = note || '';
    eval('$changeMe' + setter);
    var result = eval('$changeMe' + getter);
    $log.append('<tr><td><code>' + setter + '</code></td><td><code>' + getter + '</code></td><td>' + result + '</td><td>' + note + '</td></tr>');
})('', ".data('key')", "Initial value");

$('#changeData').click(function() {
    // set data-key to new value
    logger(".data('key', 'leia')", ".data('key')", "expect leia on jQuery node object but DOM stays as luke");
    // try and set data-key via .attr and get via some methods
    logger(".attr('data-key', 'yoda')", ".data('key')", "expect leia (still) on jQuery object but DOM now yoda");
    logger("", ".attr('key')", "expect undefined (no attr <code>key</code>)");
    logger("", ".attr('data-key')", "expect yoda in DOM and on jQuery object");

    // bonus points
    logger('', ".data('data-key')", "expect undefined (cannot get via this method)");
    logger(".data('anotherKey')", ".data('anotherKey')", "jQuery 1.6+ get multi hyphen <code>data-another-key</code>");
    logger(".data('another-key')", ".data('another-key')", "jQuery < 1.6 get multi hyphen <code>data-another-key</code> (also supported in jQuery 1.6+)");

    return false;
});

$('#changeData').click();

古いデモ


元の答え

このHTMLの場合:

<div id="foo" data-helptext="bar"></div>
<a href="#" id="changeData">change data value</a>

そして、このJavaScript(jQuery 1.6.2を使用)

console.log($('#foo').data('helptext'));

$('#changeData').click(function() {
    $('#foo').data('helptext', 'Testing 123');
//  $('#foo').attr('data-helptext', 'Testing 123');
    console.log($('#foo').data('data-helptext'));
    return false;
});

デモを見る

使用クロームデベロッパーツール コンソールの DOMを検査する、$('#foo').data('helptext', 'Testing 123'); しないで見られるように値を更新コンソールが、$('#foo').attr('data-helptext', 'Testing 123');ありません。


1
何が変わったのか
わかり

それでは、jQueryの2番目の引数を使用できる点は何ですか?js変数キャッシュに保存されている値を更新するには?
ahnbizcad 14

@gwho私はあなたの質問を完全に理解しているとは思いませんが、jQuery 1.6.2を使用して2011年の元の回答を参照していると思います。もしそうなら、それから。data('key', 'value')メソッド jQueryキャッシュの値を更新しますが、パフォーマンス上の理由(私はDOMの変更だと思います)により、DOM自体は更新されません。
andyb 14

2
したがって、DOMを更新したい場合は、更新した.attr('key','value')かどうかに関係なく、更新する必要があり.data('key', 'value')ます。それは私には冗長に思えますが、キャッシュされたDOMに書き込みをしたいが実際のDOMには書き込まないようなシナリオを想像するのに苦労しています。多分私はjQueryキャッシュを理解していません。それでは、訪問者は.data()画面上で変更されるすべてのものを見るでしょうか、それともそうではないでしょうか?
ahnbizcad 2014

1
したがって、それはパフォーマンスの問題だけではありません。それらを比較することはできません。それらは完全に異なる目的を持っており、DOMの異なる「バージョン」を変更します。質問に戻ります。ACUTALDOMを変更するために.attr()を実行する必要がある場合、.data()を使用するポイントは何ですか?冗長なようです。
ahnbizcad 14

34

私は深刻な問題を抱えていました

.data('property', value);

data-property属性を設定していませんでした。

jQueryの使用を開始.attr()

一致する要素のセットの最初の要素の属性の値を取得するか、一致するすべての要素に1つ以上の属性を設定します。

.attr('property', value)

値を設定し、

.attr('property')

値を取得します。

今ではうまくいきます!


1
私はdata()を使用してdataプロパティを変更できましたが、開発者ツールでは変更が表示されないことに気づきました。そのため、attr()を使用しました
drooh

8

@andybの受け入れられた回答には小さなバグがあります。上記の彼の投稿に対する私のコメントに加えて...

このHTMLの場合:

<div id="foo" data-helptext="bar"></div>
<a href="#" id="changeData">change data value</a>

次のように属性にアクセスする必要があります。

$('#foo').attr('data-helptext', 'Testing 123');

しかし、このようなデータメソッド:

$('#foo').data('helptext', 'Testing 123');

上記の.data()メソッドの修正により、「未定義」が防止され、データ値が更新されます(HTMLは更新されません)。

「data」属性のポイントは、要素に値をバインド(または「リンク」)することです。onclick="alert('do_something')"アクションを要素にバインドする属性に非常に似ています...テキストは役に立たないので、要素をクリックしたときにアクションが機能するだけです。

データまたはアクションが要素にバインドされると、アプリケーション(JavaScript)が使用するため、通常はHTMLを更新する必要はなく、データまたはメソッドのみを更新します。パフォーマンスの点では、とにかくHTMLも更新する理由がわかりません。html属性が表示されません(Firebugまたは他のコンソールを除く)。

あなたがそれについて考えたくなるかもしれない一つの方法:HTML(と属性)は単なるテキストです。JavaScriptが使用するデータ、関数、オブジェクトなどは、別のプレーンに存在します。JavaScriptが指示された場合のみ、JavaScriptはHTMLテキストを読み取りまたは更新しますが、JavaScriptで作成したすべてのデータと機能は、Firebug(またはその他の)コンソールに表示されるHTMLテキスト/属性とは完全に分離して機能します。

* 通常は強調します。HTMLを保存してエクスポートする必要がある場合(たとえば、ある種のマイクロフォーマット/データ対応テキストエディター)、HTMLが別のページに新鮮に読み込まれる場合は、HTMLを更新する必要があるためです。あまりにも。


ありがとう。これは、他のすべての回答の中で、間違った例で役に立ちました!data中にはattr('data-helptext'受け入れ答え、多くの票を持つものが働いていない違いを、作ります。+1
アレクス

6

私にも同じことが起こりました。それが判明

var data = $("#myObject").data();

書き込み不可能なオブジェクトを提供します。私はそれを使ってそれを解決しました:

var data = $.extend({}, $("#myObject").data());

そして、それ以来data、標準の書き込み可能なJSオブジェクトでした。


その後、それにどのように書き込みますか?
生活のために働く

申し訳ありませんがトム、私がやった後...あなたは何を意味するか分からない$.extend...、あなたが使用することができdataますようくださいdata.name = 'Nico'; data.questionSolved = true;、そしてconsole.log(data)この新しく追加されたプロパティが表示されます
ニコ

3

引用を引用するには:

data-属性は、最初にdataプロパティにアクセスしたときにプルされ、その後はアクセスまたは変更されません(すべてのデータ値はjQueryに内部的に保存されます)。

.data() -jQueryドキュメント化

この(率直に奇妙な)制限は、の使用に対してのみ保留されることに注意してください.data()

ソリューション?.attr代わりに使用してください。

もちろん、専用の方法を使用しないと不快に感じる人もいます。次のシナリオを検討してください。

  • 「標準」が更新され、カスタム属性のデータ部分が不要になった/置き換えられた

常識-なぜ彼らはそのようにすでに確立された属性を変えるのでしょうか?想像classに改名始めるグループid識別子。インターネットは壊れるでしょう。

そしてそれでも、JavaScript自体はこれを修正する能力を持っています-そしてもちろん、それはHTMLとの悪名高い非互換性にもかかわらず、REGEX(およびさまざまな同様のメソッド)があなたの属性をこの新しい神話的な「標準」にすばやく名前変更する可能性があります。

TL; DR

alert($(targetField).attr("data-helptext"));

1

前述のように、.data()メソッドは実際にはdata-属性の値を設定せず、data-属性が変更された場合でも更新された値を読み取りません。

私の解決策は.realData()、実際に属性の現在の値に対応するメソッドでjQueryを拡張することでした。

// Alternative to .data() that updates data- attributes, and reads their current value.
(function($){
  $.fn.realData = function(name,value) {
      if (value === undefined) {
        return $(this).attr('data-'+name);
      } else {
        $(this).attr('data-'+name,value);
      }
  };
})(jQuery);

注:もちろん使用できます.attr()が、私の経験から、ほとんどの開発者(別名私)は表示.attr()を間違えたり.data()、交換可能であったりし、考えずに一方を他方の代わりに使用することがよくあります。ほとんどの場合機能しますが、特に動的データバインディングの種類を処理する場合に、バグを導入するための優れた方法です。したがって、を使用.realData()することで、意図した動作をより明確にすることができます。


0

同じ問題があった。.data()メソッドを使用してもデータを取得できるため、要素に書き込む方法を理解するだけで済みます。これは私が使用するヘルパーメソッドです。ほとんどの人が言ったように、.attrを使用する必要があります。私はそれを_に置き換えています-私が知っているように 私はそれが置き換える他の文字を知りません...しかし、私はそれを研究していません。

function ExtendElementData(element, object){
    //element is what you want to set data on
    //object is a hash/js-object
    var keys = Object.keys(object);
    for (var i = 0; i < keys.length; i++){
        var key = keys[i];
        $(element).attr('data-'+key.replace("_", "-"), object[key]);
    }
}

編集:2017年5月1日

組み込みのメソッドを使用して正しいデータを取得できないインスタンスがまだあることがわかったので、現在使用しているのは次のとおりです。

function setDomData(element, object){
    //object is a hash

    var keys = Object.keys(object);
    for (var i = 0; i < keys.length; i++){
        var key = keys[i];
        $(element).attr('data-'+key.replace("_", "-"), object[key]);
    }
};

function getDomData(element, key){
    var domObject = $(element).get(0);
    var attKeys = Object.keys(domObject.attributes);

    var values = null;
    if (key != null){
        values = $(element).attr('data-' + key);
    } else {
        values = {};

        var keys = [];
        for (var i = 0; i < attKeys.length; i++) {
            keys.push(domObject.attributes[attKeys[i]]);
        }

        for (var i = 0; i < keys.length; i++){
            if(!keys[i].match(/data-.*/)){
                values[keys[i]] = $(element).attr(keys[i]);
            }
        }
    }
    return values;
};
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.