我想对大量元素使用 .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>');
输出:
Where dummy=foo :1
Where dummy=bar :0
对于选择器引擎来说,选择器中仅使用原始值。
更新 - 为最初的答案欢呼,这实际上是故意的。 .data
以 data-*
值开头,但设置自己的副本。我不想将对 .data(
的每次调用替换为对 .attr('data-' +
.
为了解决这个问题,我使用了 .filter
和一个函数,但由于这个过滤器将运行大量元素,我不想为每个匹配创建一个新的 jQuery 对象。针对这种情况jQuery提供了一些全局函数。
基本上我应该能够使用 $.data(element,
而不是 $(element).data(
),但这也不起作用:$.data(element,
返回未定义
。
所以我的代码最终类似于 .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>');
输出:
$.data before: undefined
new $(): foo
$.data after: foo
奇怪。没关系,问题是我可以解决这个问题吗?有没有什么方法可以初始化新的$
对象发生的任何事情,而无需为每个测试节点创建一个对象?
JS Fiddle 演示:http://jsfiddle.net/kU4th/
最佳答案
这不是一个错误,它只是设计得很困惑的行为。
The problem is that the jQuery selector seems to use the original value. If I set a data value using $('whatever').data('key', newValue) and then try to use a selector $('[data-key=newValue]') then nothing is found.
这是因为 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')
会返回该对象。该对象无法存储在属性中。
到目前为止,你并不是第一个被这个令人惊讶的设计烧伤的人。 :-)
<小时/>Basically I should be able to use
$.data(element
, instead of$(element).data(
, but this doesn't work either:$.data(element
, returnsundefined
.
对。 documentation for $.data
告诉你原因:
Note: This is a low-level method; a more convenient
.data()
is also available.Regarding HTML5 data-* attributes: This low-level method does NOT retrieve the data-* attributes unless the more convenient
.data()
method has already retrieved them.
您说过您不想将对 data
的调用替换为对 attr
的调用,但我不得不说这似乎是最好的情况,所以您实际上可以在选择器中使用这些 data-*
属性。
或者,您可以这样做:
matchingElements.filter(function(){
return ($.data(this, key) || this.getAttribute('data-' + key)) === value;
});
...它首先查看 data
数据,如果它返回一个 false 值 (undefined
, null
, ""
、false
、NaN
或 0
),而是从元素获取属性。如果您想将其限制为未定义
:
matchingElements.filter(function(){
var value = $.data(this, key);
return typeof value === "undefined" ? this.getAttribute('data-' + key) : value;
});
关于jquery - 我可以按使用 jQuery.data 设置的值进行过滤吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18121493/