1

我想对.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(to .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>');

输出:

$.data 之前:未定义

新 $(): foo

$.data 之后:foo

诡异的。没关系,问题是我可以解决它吗?有没有办法初始化一个新$对象发生的任何事情,而不为每个测试节点创建一个?

JS Fiddle 演示:http: //jsfiddle.net/kU4th/

4

3 回答 3

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.

正确的。的文档$.data告诉您原因:

注意:这是一种低级方法;还有一个更方便.data()的。

关于 HTML5 data-* 属性:这个低级方法不会检索 data-* 属性,除非更方便的.data()方法已经检索到它们。

你说过你不想用调用替换调用datato attr,但我不得不说这似乎是最好的情况,所以你实际上可以data-*在选择器中使用这些属性。

或者,您可以这样做:

matchingElements.filter(function(){
    return ($.data(this, key) || this.getAttribute('data-' + key)) === value;
});

...它首先查看data数据,如果它返回一个虚假值(undefinednull""falseNaN0),则改为从元素中获取属性。如果您想将其限制为undefined

matchingElements.filter(function(){
    var value = $.data(this, key);
    return typeof value === "undefined" ? this.getAttribute('data-' + key) : value;
});
于 2013-08-08T08:40:20.937 回答
1

jquery 的 data 方法和 HTML5 的 data-* 属性是完全不同的动物。

请参阅文档

关于 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');
于 2013-08-08T08:40:41.227 回答
1

jQuery 读取数据属性,但随后数据与属性分开存储。在元素上设置数据不会影响属性。

如果您还希望更改属性,则需要使用attr方法来设置值而不是data方法:

$('#test').attr('data-dummy', 'bar');

这将设置元素的data-dummy属性和元素的值data('dummy')

于 2013-08-08T08:44:50.007 回答