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

我在 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属性设置为“ Testing123”的调用不起作用。“ Old Text”仍然是属性的当前值。

我是否错误地使用了 data ()调用?我在网上查过了,看不出我哪里做错了。

下面是 HTML 标记:

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

这是在 .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 Data vs Attr? ?

超文本标示语言

<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');更新。

我也是,结果发现

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

给你一个不可写的对象,我用:

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

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

@ 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”属性的要点是将值与元素绑定(或“ link”)。非常类似于 onclick="alert('do_something')"属性,它将一个操作绑定到元素... 文本是无用的,你只需要操作在单击元素时工作即可。

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

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

* 我之所以强调 通常,是因为如果你需要保存和导出 HTML (例如某种微格式/数据感知的文本编辑器) ,在这种情况下,HTML 会在另一个页面上加载新的内容,那么你可能也需要更新 HTML。

我有严重的问题

.data('property', value);

它没有设置 data-property属性。

开始使用 jQuery 的 .attr():

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

.attr('property', value)

设置值和

.attr('property')

检索值。

现在好了!

引用一句话:

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

JQuery 文档

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

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

当然,你们中的一些人可能会因为不使用它的专用方法而感到不舒服:

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

常识——他们为什么要像那样改变 已经建立属性?想象一下,class开始被重命名为 小组,而 id被重命名为 标识符。网络会崩溃的。

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

DR

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

也有同样的问题。因为仍然可以使用。Data ()方法,您只需要找到一种写入元素的方法。这是我使用的 helper 方法。就像大多数人说的,你将不得不使用。攻击。我让它把 any _ 替换成-我知道它是这么做的。我不知道还有其他角色被取代了,不过我还没有研究过这个。

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

如前所述,.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()是可以互换的,并且经常不假思索地用一个代替另一个。它可能在大多数情况下工作,但是它是引入 bug 的一个很好的方法,特别是在处理任何类型的动态数据绑定时。因此,通过使用 .realData(),我可以更明确地说明预期的行为。