我可以按照jQuery.data设置的值进行过滤

时间:2013-08-08 08:38:08

标签: jquery custom-data-attribute jquery-filter

我想对我检查.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

看起来,对于选择器引擎,只在选择器中使用原始值。

更新 - 为初步答案欢呼,这实际上是故意的。 .datadata-*值开头,但设置了自己的副本。我不想通过调用.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/

3 个答案:

答案 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-*属性匹配,如果是,则使用该值初始化数据缓存。此时,datadata-*属性之间存在进一步关联。

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""falseNaN0undefined),转而从元素获取属性。如果您想将其限制为仅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')的值。