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')
选择带有classbig
或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
它是有效的。请参阅。感谢您提供了详尽的答案。您知道使用HTML5data-*
属性并在其上选择是否比在上选择更快吗