无法使用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()调用工作正常,它在警报对话框中显示文本“ Old Text”。但是,将data-helptext属性设置为“测试123” 的调用不起作用。“旧文本”仍然是属性的当前值。

我是否使用了对data()的错误调用?我已经在网上查询了一下,但看不到自己在做什么。

这是HTML标记:

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

代码看起来不错。这个演示没有问题。您正在使用哪个版本的jQuery?
andyb 2011年

我正在使用ASP.NET MVC项目模板随附的1.5.1。可能是我需要更新jQuery吗?
詹森·埃文斯

好的,那不是jQuery的版本。我以为它可能是一个很旧的版本。您正在使用的data()API已在v1.2.3中添加
andyb 2011年

您可以添加标记吗?您是否正在使用自定义HTML5 data-属性?
andyb 2011年

您如何观察价值?jQuery不会正确地更新它,但不会将值持久化回DOM。请参阅下面的测试和解释说明我的答案
andyb 2011年

Answers:


239

文档中提到.data()

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

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

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

更新的答案

再次,从.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 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;
});

观看演示

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


1
不知道发生了什么变化,但是您的小提琴演示在chrome控制台中返回未定义
manubkk 2013年

那么,jQuery允许您输入第二个参数的目的是什么?要更新存储在js变量缓存中的值?
ahnbizcad 2014年

@gwho我不确定我是否完全理解您的问题,但是我假设您使用的是jQuery 1.6.2,指的是2011年的原始答案。如果是这样,则。data('key', 'value')方法确实会更新jQuery缓存中的值,但是由于性能原因(我猜是DOM突变),DOM本身并未更新。
andyb 2014年

2
因此,如果您想更新DOM,则.attr('key','value')无论是否做了,都需要这样做.data('key', 'value'),对吗?对我来说,这似乎是多余的,而且我在想象一个场景中想要写入缓存的DOM,而不是真正的DOM时遇到了麻烦。也许我不了解jQuery缓存;那么访问者.data()会在屏幕上看到所有修改过的东西吗?
ahnbizcad 2014年

1
因此,这不仅仅是性能问题;他们无法比较。它们具有完全不同的目的,并且它们更改DOM的不同“版本”。回到问题所在:如果必须执行.attr()来更改ACUTAL DOM,那么使用.data()有什么意义呢?似乎多余。
ahnbizcad 2014年

34

我有严重的问题

.data('property', value);

它没有设置data-property属性。

开始使用jQuery的.attr()

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

.attr('property', value)

设置值和

.attr('property')

检索值。

现在就可以了!


1
对我来说,我可以使用data()更改data属性,但是我确实在开发人员工具中注意到它没有显示更改,因此出于这个原因,我选择了attr()
drooh 2016年

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

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

将数据或操作绑定到元素后,通常*无需更新HTML,仅需要更新数据或方法,因为这就是您的应用程序(JavaScript)使用的内容。在性能方面,我不明白为什么无论如何也要更新HTML,没有人看到html属性(在Firebug或其他控制台中除外)。

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

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


谢谢。除其他示例错误答案外,这有帮助!将dataattr('data-helptext'产生变化,其中公认的答案,并与许多票的人没有工作。+1
Aleks

6

对我来说也一样。原来是

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

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

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

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


那你怎么写呢?
谋生的作品

抱歉,汤姆,我不知道你的意思是……完成后$.extend...,您可以随意使用datadata.name = 'Nico'; data.questionSolved = true;console.log(data)并将显示此新添加的属性
Nico

3

引用报价:

数据属性在第一次访问数据属性时被拉出,然后不再被访问或变异(所有数据值然后内部存储在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]);
    }
}

编辑:5/1/2017

我发现仍然存在无法使用内置方法获取正确数据的实例,因此我现在使用的方法如下:

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;
};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.