jquery数据选择器

jquery数据选择器,jquery,jquery-selectors,Jquery,Jquery Selectors,我需要根据元素的.data()对象中存储的值来选择元素。至少,我希望使用选择器选择顶级数据属性,可能如下所示: $('a').data("category","music"); $('a:data(category=music)'); $('a').data("artist",{id: 3281, name: "Madonna"}); $('a').data("category","music"); $('a[:category=music && :artist.name=Ma

我需要根据元素的
.data()
对象中存储的值来选择元素。至少,我希望使用选择器选择顶级数据属性,可能如下所示:

$('a').data("category","music");
$('a:data(category=music)');
$('a').data("artist",{id: 3281, name: "Madonna"});
$('a').data("category","music");
$('a[:category=music && :artist.name=Madonna]');
$('a[data-attribute=true]')
或者,选择器可能采用常规属性选择器格式:

$('a[category=music]');
或属性格式,但带有一个说明符以指示它在
.data()
中:

我发现它看起来很简单,但很好。选择器设置了该页面上显示的镜像方法上方的格式。还有这个

出于某种原因,我记得不久前读到jQuery 1.4将包括对jQuery
.data()
对象中的值的选择器的支持。然而,现在我正在寻找它,我找不到它。也许这只是我看到的一个功能要求。是否有人支持这一点,而我只是看不到

理想情况下,我希望使用点表示法支持data()中的子属性。像这样:

$('a').data("user",{name: {first:"Tom",last:"Smith"},username: "tomsmith"});
$('a[:user.name.first=Tom]');
我还希望支持多个数据选择器,其中只找到具有所有指定数据选择器的元素。常规jquery多选择器执行OR操作。例如,
$('a.big,a.small')
选择带有class
big
small
a
标记。我在找一个,也许是这样的:

$('a').data("category","music");
$('a:data(category=music)');
$('a').data("artist",{id: 3281, name: "Madonna"});
$('a').data("category","music");
$('a[:category=music && :artist.name=Madonna]');
$('a[data-attribute=true]')
最后,如果数据选择器上有比较运算符和正则表达式功能,那就太好了。因此,
$(a[:artist.id>5000])
是可能的。我意识到我可能可以使用
filter()
来完成大部分工作,但是如果有一个简单的选择器格式就好了

有什么解决方案可以做到这一点?Jame的Padolsey是目前最好的解决方案吗?我主要关注的是性能,但也关注额外的特性,如子属性点表示法和多个数据选择器。是否有其他实现支持这些东西,或者在某些方面更好

有一种方法可以做到这一点:)

基于您的问题的一些示例:

$('a:data("category=music")')
$('a:data("user.name.first=Tom")');
$('a:data("category=music"):data("artist.name=Madonna")');
//jQuery supports multiple of any selector to restrict further, 
//just chain with no space in-between for this effect
与可能的情况相比,性能不会非常好,从
$中选择缓存并获取相应的元素是目前为止最快的,但是在获取内容的方式方面要更全面,而且不是很“jQuery-ey”(通常从元素方面)。在我看来,我不确定这是否是最快的,因为从唯一Id到元素的过程在性能方面是复杂的


您提到的比较选择器最好在一个插件中进行,插件中没有内置的支持,尽管您可以轻松地将其添加到插件中。

我创建了一个新的
数据
选择器,它应该允许您执行嵌套查询和条件。用法:

$('a:data(category==music,artist.name==Madonna)');
模式是:

:data( {namespace} [{operator} {check}]  )
“操作员”和“检查”是可选的。因此,如果您只有
:data(a.b.c)
,它将简单地检查
a.b.c
的真实性

您可以在下面的代码中看到可用的运算符。其中包括允许正则表达式测试的
~=

$('a:data(category~=^mus..$,artist.name~=^M.+a$)');
我已经用一些变体对它进行了测试,它似乎工作得很好。我可能很快会将其添加为Github回购(带有完整的测试套件),所以请注意

守则:

(function(){

    var matcher = /\s*(?:((?:(?:\\\.|[^.,])+\.?)+)\s*([!~><=]=|[><])\s*("|')?((?:\\\3|.)*?)\3|(.+?))\s*(?:,|$)/g;

    function resolve(element, data) {

        data = data.match(/(?:\\\.|[^.])+(?=\.|$)/g);

        var cur = jQuery.data(element)[data.shift()];

        while (cur && data[0]) {
            cur = cur[data.shift()];
        }

        return cur || undefined;

    }

    jQuery.expr[':'].data = function(el, i, match) {

        matcher.lastIndex = 0;

        var expr = match[3],
            m,
            check, val,
            allMatch = null,
            foundMatch = false;

        while (m = matcher.exec(expr)) {

            check = m[4];
            val = resolve(el, m[1] || m[5]);

            switch (m[2]) {
                case '==': foundMatch = val == check; break;
                case '!=': foundMatch = val != check; break;
                case '<=': foundMatch = val <= check; break;
                case '>=': foundMatch = val >= check; break;
                case '~=': foundMatch = RegExp(check).test(val); break;
                case '>': foundMatch = val > check; break;
                case '<': foundMatch = val < check; break;
                default: if (m[5]) foundMatch = !!val;
            }

            allMatch = allMatch === null ? foundMatch : allMatch && foundMatch;

        }

        return allMatch;

    };

}());
(函数(){

var matcher=/\s*(?:(?:(?:\\\\.[^,])+\?)+)\s*([!~>此时我选择如下:

$('a').data("category","music");
$('a:data(category=music)');
$('a').data("artist",{id: 3281, name: "Madonna"});
$('a').data("category","music");
$('a[:category=music && :artist.name=Madonna]');
$('a[data-attribute=true]')
这似乎很好,但如果jQuery能够通过该属性进行选择而不使用“data-”前缀,那就太好了


我还没有用通过jQuery动态添加到元素的数据来测试这一点,因此这可能是该方法的失败之处。

我想警告您,
$('a[data attribute=true')
不起作用,正如Ashley的回答,如果您通过data()函数将数据附加到DOM元素

如果您在HTML中添加了实际的数据属性,那么它的工作原理与您预期的一样,但是jQuery将数据存储在内存中,因此您从
$('a[data attribute=true')
获得的结果将不正确


您需要使用数据插件,使用Dmitri的
过滤器
解决方案,或者对所有元素执行$。每个元素都执行一次$。然后反复检查.data()

您还可以使用一个简单的过滤函数,而不使用任何插件。这并不完全是您想要的,但结果是相同的:

$('a').data("user", {name: {first:"Tom",last:"Smith"},username: "tomsmith"});

$('a').filter(function() {
    return $(this).data('user') && $(this).data('user').name.first === "Tom";
});

如果您也使用jQueryUI,您将获得一个(简单)版本的
:data
选择器,用于检查数据项的存在,因此您可以执行类似
$(“div:data(view)”)
$(this.closest(“:data(view)”)
的操作


看。我不知道他们已经拥有它多久了,但它现在已经存在了!

您可以使用
attr()
在elm上设置
data-*
属性,然后选择使用该属性:

var elm = $('a').attr('data-test',123); //assign 123 using attr()
elm = $("a[data-test=123]"); //select elm using attribute
现在对于该elm,
attr()
data()
都将产生123

console.log(elm.attr('data-test')); //123
console.log(elm.data('test')); //123
但是,如果使用
attr()
将值修改为456
data()
仍将是123

elm.attr('data-test',456); //modify to 456
elm = $("a[data-test=456]"); //reselect elm using new 456 attribute

console.log(elm.attr('data-test')); //456
console.log(elm.data('test')); //123
因此,据我所知,如果不需要,您可能应该避免在代码中混用
attr()
data()
命令。因为
attr()
似乎与DOM直接对应,而
data()
与“内存”交互,虽然它的初始值可以来自DOM。但关键的一点是,两者不一定是同步的

所以要小心

无论如何,如果您不更改DOM或内存中的
data-*
属性,那么就不会有问题。一旦开始修改值,就可能出现潜在问题


感谢@Clarence Liu对@Ash的回答,以及。

这里有一个简化生活的插件

这样使用:

data selector           jQuery selector
  $$('name')              $('[data-name]')
  $$('name', 10)          $('[data-name=10]')
  $$('name', false)       $('[data-name=false]')
  $$('name', null)        $('[data-name]')
  $$('name', {})          Syntax error

它是有效的。请参阅。

感谢您提供了详尽的答案。您知道使用HTML5
data-*
属性并在其上选择是否比在上选择更快吗