我需要根据存储在元素的.data()
对象中的值来选择元素。至少,我想使用选择器选择顶级数据属性,可能是这样的:
$('a').data("category","music");
$('a:data(category=music)');
或者选择器可能采用常规属性选择器格式:
$('a[category=music]');
或者以属性格式,但使用说明符表示它位于.data()
:
$('a[:category=music]');
我发现James Padolsey's implementation看起来很简单但很好。选择器格式化在该页面上显示的镜像方法。还有Sizzle patch。
出于某种原因,我记得有一段时间回顾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')
会选择a
或big
类的small
个标记。我正在寻找一个AND,也许是这样的:
$('a').data("artist",{id: 3281, name: "Madonna"});
$('a').data("category","music");
$('a[:category=music && :artist.name=Madonna]');
最后,如果数据选择器上有比较运算符和正则表达式功能,那将会很棒。所以$(a[:artist.id>5000])
是可能的。我意识到我可以使用filter()
做很多事情,但是有一个简单的选择器格式会很好。
有哪些解决方案可以做到这一点? Jame的Padolsey是目前最好的解决方案吗?我主要关注的是性能,还有子属性点符号和多数据选择器等额外功能。是否有其他实现支持这些内容或以某种方式更好?
答案 0 :(得分:175)
目前我选择这样:
$('a[data-attribute=true]')
这似乎工作得很好,但如果jQuery能够通过没有'data-'前缀的属性进行选择,那就太好了。
我没有使用动态通过jQuery添加到元素的数据对此进行测试,因此这可能是此方法的垮台。
答案 1 :(得分:102)
我创建了一个新的data
选择器,可以让您进行嵌套查询和AND条件。用法:
$('a:data(category==music,artist.name==Madonna)');
模式是:
:data( {namespace} [{operator} {check}] )
“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;
};
}());
答案 2 :(得分:83)
您也可以使用简单的过滤功能而无需任何插件。这不是你想要的,但结果是一样的:
$('a').data("user", {name: {first:"Tom",last:"Smith"},username: "tomsmith"});
$('a').filter(function() {
return $(this).data('user') && $(this).data('user').name.first === "Tom";
});
答案 3 :(得分:24)
如果您通过data()函数将数据附加到DOM元素,我想警告您$('a[data-attribute=true]')
根据Ashley的回复不起作用。
如果您在HTML中添加了一个实际的data-attr,它可以正常工作,但是jQuery将数据存储在内存中,因此从$('a[data-attribute=true]')
获得的结果将不正确。
您需要使用数据插件http://code.google.com/p/jquerypluginsblog/,使用Dmitri的filter
解决方案,或对所有元素执行$ .each并迭代检查.data()
答案 4 :(得分:11)
有:data()
filter plugin这样做:)
基于您的问题的一些示例:
$('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
与可能的相比,性能不会太高,从$._cache
中选择并抓住相应的元素是迄今为止最快的,但更多的是围绕就你如何得到东西而言,并不是非常“jQuery-ey”(你通常从元素方面进入)。在我的头脑中,我不确定这是否是最快的,因为从性能ID到元素的过程在性能方面本身就是错综复杂的。
您提到的比较选择器最好在.filter()
中进行,插件中没有内置支持,但您可以毫不费力地添加它。
答案 5 :(得分:7)
您可以使用data-*
在榆树上设置attr()
属性,然后选择使用该属性:
var elm = $('a').attr('data-test',123); //assign 123 using attr()
elm = $("a[data-test=123]"); //select elm using attribute
现在对于那个榆树,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的回答,以及this post。
答案 6 :(得分:6)
$('a[data-category="music"]')
答案 7 :(得分:5)
如果你也使用jQueryUI,你会得到:data
选择器的(简单)版本,它会检查是否存在数据项,因此你可以做$("div:data(view)")
或{$( this ).closest(":data(view)")
之类的事情。 {1}}。
见http://api.jqueryui.com/data-selector/。我不知道他们有多久了,但现在就在那里!
答案 8 :(得分:3)
这是一个简化生活的插件https://github.com/rootical/jQueryDataSelector
使用它:
data selector jQuery selector
$$('name') $('[data-name]')
$$('name', 10) $('[data-name=10]')
$$('name', false) $('[data-name=false]')
$$('name', null) $('[data-name]')
$$('name', {}) Syntax error