jQuery的数据select器

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

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

或者select器可能是常规的属性select器格式:

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

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

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

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

出于某种原因,我回想起来,jQuery 1.4会包含对jquery .data()对象中值的select器的支持。 但是,现在我正在寻找它,我找不到它。 也许这只是我看到的一个function请求。 有没有支持这个,我只是没有看到它?

理想情况下,我想用点符号来支持data()中的子属性。 喜欢这个:

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

我也想支持多个数据select器,其中只有具有所有指定的数据select器的元素被发现。 常规的jQuery多重select器执行OR操作。 例如, $('a.big, a.small')selectabigsmall a标签)。 我正在寻找一个AND,也许是这样的:

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

最后,比较运算符和正则expression式在数据select器上是可用的。 所以$(a[:artist.id>5000])将是可能的。 我意识到我可以用filter()来做很多事情,但是有一个简单的select器格式会很好。

有什么解决scheme可以做到这一点? Jame的Padolsey是目前最好的解决scheme吗? 我关心的主要是性能方面的问题,还有像属性点符号和多个数据select器这样的额外function。 有其他的实现支持这些东西,或者以某种方式更好吗?

我已经创build了一个新的dataselect器,使您能够进行嵌套查询和AND条件。 用法:

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

模式是:

 :data( {namespace} [{operator} {check}] ) 

“操作员”和“检查”是可选的。 所以,如果你只有:data(abc)它只会检查abc真实性

您可以在下面的代码中看到可用的运算符。 其中有~=允许正则expression式testing:

 $('a:data(category~=^mus..$,artist.name~=^M.+a$)'); 

我已经testing了一些变化,似乎工作得很好。 我可能会很快添加这个作为一个Github回购(一个完整的testing套件),所以保持警惕!

代码:

 (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; }; }()); 

目前我select这样的:

 $('a[data-attribute=true]') 

这似乎工作得很好,但如果jQuery能够通过该属性select没有“数据”前缀将是很好的。

我没有testing这个数据通过jQuerydynamic添加到元素,所以这可能是这种方法的失败。

你也可以使用一个简单的过滤function,没有任何插件。 这不是你想要的,但结果是一样的:

 $('a').data("user", {name: {first:"Tom",last:"Smith"},username: "tomsmith"}); $('a').filter(function() { return $(this).data('user') && $(this).data('user').name.first === "Tom"; }); 

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

如果你在HTML中添加一个实际的data-attr,但是jQuery将数据存储在内存中,所以你从$('a[data-attribute=true]')结果不会是正确的。

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

有一个: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 

可能情况相比,性能并不会很好,从$._cacheselect,抓取相应的元素是迄今为止最快的,但更多的是围绕在jQuery-ey上,而不是“jQuery-ey”你得到的东西(你通常从元素方进来)。 在我头顶,我不确定这是否是最快的,因为从独特的Id到元素的过程在性能方面本身是错综复杂的。

你提到的比较select器最好在.filter()做,在插件中没有内置的支持,尽pipe你可以在没有很多麻烦的情况下添加它。

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

 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()与“内存”相互作用,尽pipe它的初始值可以来自DOM。 但关键是两者不一定是同步的。

所以要小心点

无论如何,如果你不改变DOM或内存中的data-*属性,那么你就不会有问题了。 不久,当你开始修改值是潜在的问题可能出现的时候。

感谢@Clarence Liu给@Ash的回答,还有这个post 。

 $('a[data-category="music"]') 

有用。 请参阅属性等于select器[name =“value”] 。

如果你还使用jQueryUI,你会得到一个(简单)版本的:dataselect器,它会检查数据项的存在,所以你可以做一些像$("div:data(view)")$( this ).closest(":data(view)")

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

这是一个简化生活的插件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