jquery - 我可以按使用 jQuery.data 设置的值进行过滤吗

标签 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>');

输出:

Where dummy=foo :1

Where dummy=bar :0

对于选择器引擎来说,选择器中仅使用原始值。

更新 - 为最初的答案欢呼,这实际上是故意的。 .datadata-* 值开头,但设置自己的副本。我不想将对 .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-* 属性匹配,如果匹配的话,用该值初始化数据缓存。此时,datadata-* 属性之间没有进一步的联系。

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, returns undefined.

对。 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, ""falseNaN0),而是从元素获取属性。如果您想将其限制为未定义:

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/

相关文章:

javascript - 如何隐藏/显示作用于 keyup 过滤器输入的表 div

javascript - 过滤器与从已加载数据中查找之间的 jQuery 性能测试

javascript - 如何将对象的某些部分作为字符串获取

javascript - 如何翻转元素 onclick 按钮?

jquery - tablesorter-filter 和 jquery tablesorter

JavaScript 不能在循环中使用多个 setTimeout 函数

javascript - 复选框选择/取消选择触发器第一次有效,但在后续尝试中失败

jquery - 使用 jQuery 延迟更改 CSS 属性

javascript - 如何在 jquery 中隐藏(或显示)子下拉列表(动态 html)?

jQuery 未检测到最近添加的 .data setter