小编典典

jquery 数据选择器

all

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

$('a').data("category","music");
$('a:data(category=music)');

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

$('a[category=music]');

或以属性格式,但带有说明符以指示它位于.data()

$('a[:category=music]');

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

出于某种原因,我记得不久前读过 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或) 的a标签。我正在寻找一个 AND,也许是这样的:big``small

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

最后,如果比较运算符和正则表达式功能可用于数据选择器,那就太好了。所以$(a[:artist.id>5000])才有可能。我意识到我可能可以使用filter().

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


阅读 137

收藏
2022-08-01

共1个答案

小编典典

我创建了一个新的data选择器,它应该使您能够执行嵌套查询和 AND 条件。用法:

$('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;

    };

}());
2022-08-01