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')
selecta
或big
或small
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了一个新的data
select器,使您能够进行嵌套查询和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
与可能的情况相比,性能并不会很好,从$._cache
select,抓取相应的元素是迄今为止最快的,但更多的是围绕在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,你会得到一个(简单)版本的:data
select器,它会检查数据项的存在,所以你可以做一些像$("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