我想对我检查.filter
属性的大量元素使用data-*
函数,但是它们是由.data
方法设置的。
问题是jQuery选择器总是使用原始值。如果我使用$('whatever').data('key', newValue)
设置数据值,然后尝试使用选择器$('[data-key=newValue]')
,则找不到任何内容。
这是我的测试HTML:
<div id="test" data-dummy="foo"></div>
<div id="result"</div>
然后:
$('#test').data('dummy', 'bar');
$('#result').
append('<div>Where dummy=foo: ' + $('[data-dummy="foo"]').length + '</div>').
append('<div>Where dummy=bar: ' + $('[data-dummy="bar"]').length + '</div>');
输出:
其中dummy = foo:1
其中dummy = bar:0
看起来,对于选择器引擎,只在选择器中使用原始值。
更新 - 为初步答案欢呼,这实际上是故意的。 .data
以data-*
值开头,但设置了自己的副本。我不想通过调用.data(
替换每个.attr('data-' +
来电。
要解决这个问题,我正在使用带有函数的.filter
,但由于此过滤器将针对大量元素运行,因此我不想为每个匹配创建新的jQuery对象。对于这种情况,jQuery提供了一些全局函数。
基本上我应该可以使用$.data(element,
代替$(element).data(
,但这也不起作用:$.data(element,
返回undefined
。
所以我的代码最终会像.filter(function(){return $.data(this, key) === value;})
然而,这似乎只是在初始化jQuery对象之前:
var domEle = document.getElementById('test');
var globalBefore = $.data(domEle, 'dummy');
var first = $(domEle).data('dummy');
var globalAfter = $.data(domEle, 'dummy');
$('#result').
append('<div>$.data before: ' + globalBefore + '</div>').
append('<div>new $(): ' + first + '</div>').
append('<div>$.data after: ' + globalAfter + '</div>');
输出:
$。之前的数据:undefined
new $():foo
$。数据之后:foo
怪异。没关系,问题是我可以解决它吗?有没有办法初始化新的$
对象发生的事情而不为每个测试节点创建一个?
JS小提琴演示:http://jsfiddle.net/kU4th/
答案 0 :(得分:1)
这不是一个错误,它只是一个令人困惑的设计行为。
问题是jQuery选择器似乎使用原始值。如果我使用$('whatever')。data('key',newValue)设置数据值,然后尝试使用选择器$('[data-key = newValue]'),则找不到任何内容。
那是因为data
从不设置 data-*
属性,它只是从它们初始化。它是不对称的(从它们读取但不写入它们)。
要实际更新属性,请使用attr
。例如,而不是:
$('whatever').data('key', newValue);
你需要
$('whatever').attr('data-key', newValue);
如果您想两者设置数据和属性:
$('whatever').data('key', newValue).attr('data-key', newValue);
data
使用jQuery管理的对象缓存将键/值对数据与元素相关联。如果您向data
询问元素数据缓存中尚不存在的密钥,它会查看该密钥是否与data-*
属性匹配,如果是,则使用该值初始化数据缓存。此时,data
与data-*
属性之间存在无进一步关联。
data
不回写属性的原因可能至少部分归因于您可以通过data
存储任何这一事实,而当然属性值始终是字符串。例如,如果你这样做:
$("whatever").data('key', {
nice: "complex",
obj: "here",
answer: 42,
when: new Date()
});
...然后$("whatever").data('key')
将返回该对象。该对象不能存储在属性中。
到目前为止,你不是第一个被这种令人惊讶的设计所灼伤的人。 : - )
基本上我应该可以使用
$.data(element
而不是$(element).data(
,但这不起作用:$.data(element
,返回undefined
。
右。 documentation for $.data
告诉您原因:
注意:这是一种低级方法;还可以使用更方便的
.data()
。关于HTML5 data- * attributes :这个低级方法不会检索data- *属性,除非更方便的
.data()
方法已经检索过它们。
您已经说过,您不希望通过调用data
来取代对attr
的来电,但我不得不说这似乎是最好的情况,所以您实际上可以使用data-*
matchingElements.filter(function(){
return ($.data(this, key) || this.getAttribute('data-' + key)) === value;
});
选择器中的1}}属性。
或者,你可以这样做:
data
...首先查看undefined
数据,如果它返回假名值null
,""
,false
,NaN
,0
或undefined
),转而从元素获取属性。如果您想将其限制为仅matchingElements.filter(function(){
var value = $.data(this, key);
return typeof value === "undefined" ? this.getAttribute('data-' + key) : value;
});
:
{{1}}
答案 1 :(得分:1)
jquery的数据方法和HTML5 data- *属性是完全不同的动物。
请参阅documentation:
关于HTML5 data- *属性:这个低级方法不检索data- *属性,除非更方便的.data()方法已经检索过它们。
您通过
设置的内容$(selector).data('key', value)
通过
检索var foo = $(selector).data('key')
如果您想使用html data- *属性,请使用
$(selector).attr('data-key', value)
并使用
检索它var foo = $(selector).attr('data-key');
答案 2 :(得分:1)
jQuery读取数据属性,但随后数据与属性分开存储。在元素上设置数据不会影响属性。
如果您还希望更改属性,则需要使用attr
方法设置值而不是data
方法:
$('#test').attr('data-dummy', 'bar');
这将在元素上设置data-dummy
属性,并为元素设置data('dummy')
的值。