无法使用 jQuery Data() API 设置数据属性
Posted
技术标签:
【中文标题】无法使用 jQuery Data() API 设置数据属性【英文标题】:Unable to set data attribute using jQuery Data() API 【发布时间】:2011-10-13 06:10:39 【问题描述】:我在 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="" />
【问题讨论】:
代码看起来没问题。 this demo 没问题。您使用的是哪个版本的 jQuery? 我使用的是 ASP NET MVC 项目模板附带的 1.5.1。难道是我需要更新jQuery? 好吧,那不是jQuery的版本。我在想它可能是一个非常旧的版本。您使用的 data() API 是在 v1.2.3 中添加的 您可以添加标记吗?您是否使用自定义 HTML5data-
属性?
您如何观察价值? jQuery 不会将值保存回 DOM,尽管它会正确更新它。请参阅下面的答案以进行测试和解释
【参考方案1】:
.data()
documentation中有提到
data-属性在第一次访问数据属性时被拉取,然后不再被访问或改变(所有数据值都存储在jQuery内部)
Why don't changes to jQuery $.fn.data() update the corresponding html 5 data-* attributes? 也对此进行了报道
下面我原始答案的演示似乎不再起作用了。
更新答案
再次,来自.data()
documentation
在 jQuery 1.6 中更改了对嵌入短划线的属性的处理以符合 W3C HTML5 规范。
所以对于<div data-role="page"></div>
,以下是正确的$('div').data('role') === 'page'
我很确定 $('div').data('data-role')
过去曾工作过,但现在似乎不再如此了。我创建了一个更好的展示,它将日志记录到 HTML,而不必打开控制台,并添加了一个额外的多连字符到 camelCase data- attributes 转换的示例。
Updated demo (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();
Older demo
原答案
对于这个 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;
);
See demo
使用Chrome DevTools Console 来检查 DOM,$('#foo').data('helptext', 'Testing 123');
不会 更新 Console 中看到的值,但是$('#foo').attr('data-helptext', 'Testing 123');
会。
【讨论】:
不确定发生了什么变化,但您的小提琴演示在 chrome 控制台中返回 undefined 那么,jQuery 允许您输入第二个参数的意义何在?更新js变量缓存中存储的值? @gwho 我不确定我是否完全理解您的问题,但我假设您指的是 2011 年使用 jQuery 1.6.2 的原始答案。如果是这样,那么 .data('key', 'value')
方法确实更新了 jQuery 缓存中的值,但出于性能原因(我猜是 DOM 突变)DOM 本身没有更新。
所以如果你想更新 DOM,无论你是否做了.data('key', 'value')
,你都需要做.attr('key','value')
,对吧?这对我来说似乎是多余的,而且我无法想象您想要写入缓存 DOM 而不是真正的 DOM 的场景。也许我不了解 jQuery 缓存;那么访问者会在他们的屏幕上看到.data()
修改的所有内容,还是看不到?
所以这不仅仅是性能问题;他们无法比较。它们有完全不同的目的,它们改变了 DOM 的不同“版本”。回到这个问题:如果必须使用 .attr() 来更改 ACUTAL DOM,那么使用 .data() 有什么意义?似乎是多余的。【参考方案2】:
我也遇到了同样的情况。原来,
var data = $("#myObject").data();
给你一个不可写的对象。我解决了它:
var data = $.extend(, $("#myObject").data());
从那时起,data
就是一个标准的、可写的 JS 对象。
【讨论】:
你怎么写呢? Sorry Thom,我不知道你是什么意思... 做完$.extend...
,你可以随意使用data
:data.name = 'Nico'; data.questionSolved = true;
,console.log(data)
会显示这个新添加的属性【参考方案3】:
@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。
【讨论】:
谢谢。除了错误示例的所有其他答案之外,这也有所帮助!attr('data-helptext'
中的 data
有所不同,其中接受的答案和有很多投票的答案都不起作用。 +1【参考方案4】:
我遇到了严重的问题
.data('property', value);
它没有设置data-property
属性。
开始使用 jQuery 的.attr()
:
获取集合中第一个元素的属性值 匹配的元素或为每个匹配的元素设置一个或多个属性 元素。
.attr('property', value)
设置值和
.attr('property')
检索值。
现在它可以工作了!
【讨论】:
对我来说,我可以使用 data() 更改数据属性,但我确实注意到在开发人员工具中它没有显示更改,因此我使用 attr()【参考方案5】:引用一句话:
data-属性在data属性第一次被拉取 访问,然后不再被访问或变异(所有数据值 然后在内部存储在 jQuery 中)。
.data()
- jQuery Documentiation
请注意,此(坦率地说奇怪)限制仅适用于 .data()
的使用。
解决方案?请改用.attr
。
当然,你们中的一些人可能会对不使用它的专用方法感到不舒服。考虑以下场景:
“标准”已更新,因此不再需要/替换自定义属性的数据部分常识 - 他们为什么要像那样更改 已经建立的 属性?想象一下 class
开始重命名为 group,id
开始重命名为 identifier。互联网会崩溃。
即便如此,Javascript 本身也有能力解决这个问题 - 当然,尽管它与 HTML 不兼容而臭名昭著,但 REGEX(以及各种类似的方法)可以迅速将您的属性重命名为这个新的神话“标准”。
TL;DR
alert($(targetField).attr("data-helptext"));
【讨论】:
【参考方案6】:遇到了同样的问题。由于您仍然可以使用 .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;
;
【讨论】:
【参考方案7】:如前所述,.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()
,我可以更明确地了解预期的行为。
【讨论】:
以上是关于无法使用 jQuery Data() API 设置数据属性的主要内容,如果未能解决你的问题,请参考以下文章
试图将 jquery AJAX 转换为 Fetch API,如何设置RequestHeader?
如何在 iFrame 正文标签上设置 jQuery data() 并从 iFrame 内部检索它?
使用 jquery 设置后,Jquery :data() 选择器不起作用