无法使用 jQuery Data() API 设置数据属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6827810/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 21:25:45  来源:igfitidea点击:

Unable to set data attribute using jQuery Data() API

jquerymodel-view-controllerattributescustom-data-attribute

提问by Jason Evans

I've got the following field on an MVC view:

我在 MVC 视图中有以下字段:

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

In a seperate js file, I want to set the data-helptextattribute to a string value. Here's my code:

在单独的 js 文件中,我想将该data-helptext属性设置为字符串值。这是我的代码:

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

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

The alert()call works fine, it shows the text "Old Text" in an alert dialog. However, the call to set the data-helptextattribute to "Testing 123" does not work. "Old Text" is still the attribute's current value.

alert()呼叫工作正常,它显示在警报对话框文本“古文字”。但是,将data-helptext属性设置为“Testing 123”的调用不起作用。“旧文本”仍然是属性的当前值。

Am I using the call to data() incorrectly? I've looked this up on the web, and I can't see what I'm doing wrong.

我是否错误地使用了对 data() 的调用?我在网上查过这个,我看不出我做错了什么。

Here's the HTML markup:

这是 HTML 标记:

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

回答by andyb

It is mentioned in the .data()documentation

它在文档中提到.data()

The data- attributes are pulled in the first time the data property is accessed and then are no longer accessed or mutated (all data values are then stored internally in jQuery)

数据属性在第一次访问数据属性时被拉取,然后不再访问或改变(然后所有数据值都存储在 jQuery 内部)

This was also covered on Why don't changes to jQuery $.fn.data() update the corresponding html 5 data-* attributes?

这也覆盖上)为什么不更改为jQuery的$ .fn.data(更新相应的HTML 5数据- *属性?

The demo on my original answer below doesn't seem to work any more.

我下面的原始答案中的演示似乎不再起作用。

Updated answer

更新答案

Again, from the .data()documentation

再次,从.data()文档

The treatment of attributes with embedded dashes was changed in jQuery 1.6 to conform to the W3C HTML5 specification.

jQuery 1.6 更改了对带有嵌入破折号的属性的处理,以符合 W3C HTML5 规范。

So for <div data-role="page"></div>the following is true $('div').data('role') === 'page'

所以对于<div data-role="page"></div>以下情况是正确的$('div').data('role') === 'page'

I'm fairly sure that $('div').data('data-role')worked in the past but that doesn't seem to be the case any more. I've created a better showcase which logs to HTML rather than having to open up the Console and added an additional example of the multi-hyphen to camelCase data- attributesconversion.

我相当确定这$('div').data('data-role')在过去有效,但现在似乎不再如此。我创建了一个更好的展示,它记录到 HTML 而不必打开控制台,并添加了一个额外的多连字符示例到驼峰数据属性转换。

Updated demo (2015-07-25)

更新演示 (2015-07-25)

Also see jQuery Data vs Attr?

另请参阅jQuery Data vs Attr?

HTML

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+)

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


Older demo

较旧的演示



Original answer

原答案

For this HTML:

对于此 HTML:

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

and this JavaScript (with jQuery 1.6.2)

和这个 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;
});

See demo

看演示

Using the Chrome DevToolsConsoleto inspect the DOM, the $('#foo').data('helptext', 'Testing 123');does notupdate the value as seen in the Consolebut $('#foo').attr('data-helptext', 'Testing 123');does.

使用Chrome DevTools控制台检查 DOM,$('#foo').data('helptext', 'Testing 123');不会更新控制台中看到的值,但$('#foo').attr('data-helptext', 'Testing 123');会更新。

回答by Leniel Maccaferri

I was having serious problems with

我遇到了严重的问题

.data('property', value);

It was not setting the data-propertyattribute.

它没有设置data-property属性。

Started using jQuery's .attr():

开始使用 jQuery 的.attr()

Get the value of an attribute for the first element in the set of matched elements or set one or more attributes for every matched element.

获取匹配元素集中第一个元素的属性值,或者为每个匹配元素设置一个或多个属性。

.attr('property', value)

to set the value and

设置值和

.attr('property')

to retrieve the value.

来检索值。

Now it just works!

现在它只是有效!

回答by Frank Forte

@andyb's accepted answer has a small bug. Further to my comment on his post above...

@andyb 接受的答案有一个小错误。进一步我对他上面的帖子的评论......

For this HTML:

对于此 HTML:

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

You need to access the attribute like this:

您需要像这样访问属性:

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

but the data method like this:

但是像这样的数据方法:

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

The fix above for the .data() method will prevent "undefined" and the data value will be updated (while the HTML will not)

上面对 .data() 方法的修复将防止“未定义”并且数据值将被更新(而 HTML 不会)

The point of the "data" attribute is to bind (or "link") a value with the element. Very similar to the onclick="alert('do_something')"attribute, which binds an action to the element... the text is useless you just want the action to work when they click the element.

“数据”属性的重点是将值与元素绑定(或“链接”)。非常类似于将onclick="alert('do_something')"动作绑定到元素的属性......文本是无用的,你只是希望在他们单击元素时动作起作用。

Once the data or action is bound to the element, there is usually*no need to update the HTML, only the data or method, since that is what your application (JavaScript) would use. Performance wise, I don't see why you would want to also update the HTML anyway, no one sees the html attribute (except in Firebug or other consoles).

一旦数据或操作绑定到元素,通常*无需更新 HTML,只需更新数据或方法,因为这是您的应用程序 (JavaScript) 将使用的。性能方面,我不明白你为什么还要更新 HTML,没有人看到 html 属性(除了在 Firebug 或其他控制台中)。

One way you might want to think about it: The HTML (along with attributes) are just text. The data, functions, objects, etc that are used by JavaScript exist on a separate plane. Only when JavaScript is instructed to do so, it will read or update the HTML text, but all the data and functionality you create with JavaScript are acting completely separate from the HTML text/attributes you see in your Firebug (or other) console.

您可能想要考虑的一种方式是:HTML(连同属性)只是文本。JavaScript 使用的数据、函数、对象等存在于单独的平面上。只有当 JavaScript 被指示这样做时,它才会读取或更新 HTML 文本,但是您使用 JavaScript 创建的所有数据和功能都与您在 Firebug(或其他)控制台中看到的 HTML 文本/属性完全分开。

*I put emphasis on usuallybecause if you have a case where you need to preserve and export HTML (e.g. some kind of micro format/data aware text editor) where the HTML will load fresh on another page, then maybe you need the HTML updated too.

*我通常强调,因为如果您需要保留和导出 HTML(例如某种微格式/数据感知文本编辑器),其中 HTML 将在另一个页面上重新加载,那么您可能需要更新 HTML也。

回答by Nico

Happened the same to me. It turns out that

我也发生了同样的事情。事实证明

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

gives you a non-writable object. I solved it using:

给你一个不可写的对象。我使用以下方法解决了它:

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

And from then on, datawas a standard, writable JS object.

从那时起,data就是一个标准的、可写的 JS 对象。

回答by Super Cat

To quote a quote:

引用一个报价:

The data- attributes are pulled in the first time the data property is accessed and then are no longer accessed or mutated (all data values are then stored internally in jQuery).

数据属性在第一次访问数据属性时被拉取,然后不再访问或改变(然后所有数据值都存储在 jQuery 内部)。

.data()- jQuery Documentiation

.data()- jQuery 文档

Note that this (Frankly odd) limitation is only withheld to the use of .data().

请注意,此(坦率地说很奇怪)限制仅适用于.data().

The solution? Use .attrinstead.

解决方案?使用.attr来代替。

Of course, several of you may feel uncomfortable with not using it's dedicated method. Consider the following scenario:

当然,你们中的一些人可能会对不使用它的专用方法感到不舒服。考虑以下场景:

  • The 'standard' is updated so that the data- portion of custom attributes is no longer required/is replaced
  • “标准”已更新,以便不再需要/替换自定义属性的数据部分

Common sense - Why would they change an already establishedattribute like that? Just imagine classbegin renamed to groupand idto identifier. The Internet would break.

常识 - 他们为什么要像这样改变已经建立的属性?试想class开始更名为id标识符。互联网会崩溃。

And even then, Javascript itself has the ability to fix this - And of course, despite it's infamous incompatibility with HTML, REGEX (And a variety of similar methods) could rapidly rename your attributes to this new-mythical 'standard'.

即便如此,Javascript 本身也有能力解决这个问题——当然,尽管它与 HTML 的不兼容臭名昭著,REGEX(以及各种类似的方法)可以快速将您的属性重命名为这个新的神话“标准”。

TL;DR

TL; 博士

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

回答by Yarin

As mentioned, the .data()method won't actually set the value of the data-attribute, nor will it read updated values if the data-attribute changes.

如前所述,该.data()方法实际上不会设置data-属性的值,也不会在data-属性更改时读取更新的值。

My solution was to extend jQuery with a .realData()method that actually corresponds to the current value of the attribute:

我的解决方案是使用一种.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);

NOTE:Sure you could just use .attr(), but from my experience, most developers (aka me) make the mistake of viewing .attr()and .data()as interchangeable, and often substitute one for the other without thinking. It might work most of the time, but it's a great way to introduce bugs, especially when dealing with any sort of dynamic data binding. So by using .realData(), I can be more explicit about the intended behavior.

注意:当然你可以只使用.attr(),但根据我的经验,大多数开发人员(又名我)犯了将.attr().data()视为可互换的错误,并且经常不假思索地用一个替换另一个。它可能在大部分时间都有效,但这是引入错误的好方法,尤其是在处理任何类型的动态数据绑定时。因此,通过使用.realData(),我可以更明确地了解预期的行为。

回答by Matthew Pautzke

Had the same problem. Since you can still get data using the .data() method, you only have to figure out a way to write to the elements. This is the helper method I use. Like most people have said, you will have to use .attr. I have it replacing any _ with - as I know it does that. I'm not aware of any other characters it replaces...however I have not researched that.

有同样的问题。由于您仍然可以使用 .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]);
    }
}

EDIT: 5/1/2017

编辑:2017 年 5 月 1 日

I found there were still instances where you could not get the correct data using built in methods so what I use now is as follows:

我发现仍然存在使用内置方法无法获得正确数据的情况,所以我现在使用的方法如下:

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;
};