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="" />
4

7 回答 7

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 而不必打开控制台,并添加了一个额外的多连字符到 camelCase数据属性转换的示例。

更新演示 (2015-07-25)

另请参阅jQuery 数据与 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;
});

看演示

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

于 2011-07-26T09:47:31.283 回答
35

我遇到了严重的问题

.data('property', value);

它没有设置data-property属性。

开始使用 jQuery 的.attr()

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

.attr('property', value)

设置值和

.attr('property')

检索值。

现在它只是工作!

于 2014-09-23T21:06:30.227 回答
9

@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 不会)

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

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

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

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

于 2014-09-13T03:15:24.520 回答
6

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

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

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

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

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

于 2013-12-02T16:15:10.987 回答
3

引用一个报价:

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

.data()- jQuery 文档

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

解决方案?改为使用.attr

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

  • “标准”已更新,因此不再需要/替换自定义属性的数据部分

常识——他们为什么要改变一个已经建立的属性?想象一下class开始重命名为groupidentifier。互联网会崩溃。id

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

TL;博士

alert($(targetField).attr("data-helptext"));
于 2015-01-25T03:56:28.763 回答
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(),我可以更明确地了解预期的行为。

于 2018-10-14T22:13:47.833 回答
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;
};
于 2015-11-24T20:10:54.083 回答