jquery数据选择器

Tau*_*ren 183 jquery jquery-selectors

我需要根据存储在元素.data()对象中的值来选择元素.至少,我想使用选择器选择顶级数据属性,可能是这样的:

$('a').data("category","music");
$('a:data(category=music)');
Run Code Online (Sandbox Code Playgroud)

或者选择器可能采用常规属性选择器格式:

$('a[category=music]');
Run Code Online (Sandbox Code Playgroud)

或者以属性格式,但使用说明符指示它在.data():

$('a[:category=music]');
Run Code Online (Sandbox Code Playgroud)

我发现James Padolsey的实现看起来很简单,但很好.选择器格式化在该页面上显示的镜像方法.还有这个Sizzle补丁.

出于某种原因,我记得有一段时间回顾jQuery 1.4将包含对jquery .data()对象中值的选择器的支持.但是,现在我正在寻找它,我找不到它.也许这只是我看到的一个功能请求.是否有支持,我只是没有看到它?

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

$('a').data("user",{name: {first:"Tom",last:"Smith"},username: "tomsmith"});
$('a[:user.name.first=Tom]');
Run Code Online (Sandbox Code Playgroud)

我还想支持多个数据选择器,其中只找到具有所有指定数据选择器的元素.常规jquery多选择器执行OR操作.例如,$('a.big, a.small')选择a带有类big或标签的标签small.我正在寻找一个AND,也许是这样的:

$('a').data("artist",{id: 3281, name: "Madonna"});
$('a').data("category","music");
$('a[:category=music && :artist.name=Madonna]');
Run Code Online (Sandbox Code Playgroud)

最后,如果数据选择器上有比较运算符和正则表达式功能,那将会很棒.所以$(a[:artist.id>5000])可能.我意识到我可能会做很多这样的事情filter(),但是有一个简单的选择器格式会很好.

有什么解决方案可以做到这一点?Jame的Padolsey是目前最好的解决方案吗?我主要关注的是性能,还有子属性点符号和多数据选择器等额外功能.是否有其他实现支持这些内容或以某种方式更好?

Ash*_*Ash 175

目前我选择这样:

$('a[data-attribute=true]')
Run Code Online (Sandbox Code Playgroud)

这似乎工作正常,但如果jQuery能够通过该属性选择没有'data-'前缀将是很好的.

我没有用动态jQuery添加到元素的数据测试这个,所以这可能是这个方法的垮台.

  • 如果你通过.data()函数通过JS附加/修改数据,这实际上不起作用,属性选择器只检查DOM,JS在内存中存储.data() (109认同)

Jam*_*mes 102

我创建了一个新的data选择器,它可以让你做嵌套的查询和AND条件.用法:

$('a:data(category==music,artist.name==Madonna)');
Run Code Online (Sandbox Code Playgroud)

模式是:

:data( {namespace} [{operator} {check}]  )
Run Code Online (Sandbox Code Playgroud)

"operator"和"check"是可选的.所以,如果你只有:data(a.b.c)它会简单地检查了感实性a.b.c.

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

$('a:data(category~=^mus..$,artist.name~=^M.+a$)');
Run Code Online (Sandbox Code Playgroud)

我已经用一些变化测试了它,它看起来效果很好.我很快就会把它作为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;

    };

}());
Run Code Online (Sandbox Code Playgroud)

  • @JP:你有没有把它变成一个github项目?我正在使用jQuery 1.5.1运行测试,使用选择器$("input:data(test> 400)")在输入上使用html5属性data-test ="500",但选择器没有返回任何内容. (3认同)

Dmi*_*tri 83

您也可以使用简单的过滤功能而无需任何插件.这不是你想要的,但结果是一样的:

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

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

  • 这是一个好主意,我忘了`filter`遍历函数可以接受测试函数=)谢谢 (2认同)

Cla*_*Liu 24

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

如果你在HTML中添加了一个实际的data-attr,它可以正常工作,但是jQuery将数据存储在内存中,所以你得到的结果$('a[data-attribute=true]')是不正确的.

您需要使用数据插件http://code.google.com/p/jquerypluginsblog/,使用Dmitri的filter解决方案,或对所有元素执行$ .each并迭代检查.data()


Nic*_*ver 11

这里有一个:data()过滤插件 :)

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

$('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
Run Code Online (Sandbox Code Playgroud)

可能的相比,性能并不是非常好,选择$._cache和抓取相应的元素是迄今为止最快的,但是就如何达到而言,更多的是围绕而不是非常"jQuery-ey"东西(你通常从元素方面进来).在我的头脑中,我不确定这是否是最快的,因为从性能上来说,从独特的Id到元素的过程本身就是错综复杂的.

你提到的比较选择器最好用a .filter(),插件中没有内置的支持,尽管你可以毫不费力地添加它.


D.T*_*ate 7

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

var elm = $('a').attr('data-test',123); //assign 123 using attr()
elm = $("a[data-test=123]"); //select elm using attribute
Run Code Online (Sandbox Code Playgroud)

现在对于榆树,都attr()data()将产生123:

console.log(elm.attr('data-test')); //123
console.log(elm.data('test')); //123
Run Code Online (Sandbox Code Playgroud)

但是,如果将值修改为456使用attr(),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
Run Code Online (Sandbox Code Playgroud)

据我所知,如果你不需要,你似乎应该避免代码中的混合attr()data()命令.因为attr()似乎直接与DOM对应,而data()与'memory'交互,尽管它的初始值可以来自DOM.但关键是两者并不一定是同步的.

所以要小心.

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

感谢@Clarence Liu对@ Ash的回答,以及这篇文章.


Pau*_*aul 5

如果你也使用jQueryUI,你会得到一个(简单)版本的:data选择器来检查数据项是否存在,所以你可以做类似的事情$("div:data(view)"),或者$( this ).closest(":data(view)").

http://api.jqueryui.com/data-selector/.我不知道他们有多久了,但它现在就在那里!