坚持使用官方的 jQuery API,除了使用 nextAll
和 :first
伪类之外,还有更简洁但效率更高的方法来查找匹配给定选择器的元素的下一个同级元素吗?
当我说到官方 API 时,我的意思是不要黑进内部,直接进入 Sizzle,添加一个插件,等等(如果我最终不得不这样做,那就这样做,但这不是这个问题
例如,考虑到这种结构:
<div>One</div>
<div class='foo'>Two</div>
<div>Three</div>
<div class='foo'>Four</div>
<div>Five</div>
<div>Six</div>
<div>Seven</div>
<div class='foo'>Eight</div>
如果我在 this
中有一个 div
(可能在 click
处理程序中) ,并且希望找到与选择器“ div.foo”匹配的下一个兄弟 div,我可以这样做:
var nextFoo = $(this).nextAll("div.foo:first");
... 而且它很有效(例如,如果我以“ Five”开头,它会跳过“ Six”和“ Seven”,为我找到“ Eight”) ,但它很笨重,如果我想匹配几个选择器中的任何一个,它就会笨重得多。(当然,它比原始 DOM 循环更简洁... ...)
我基本上想要:
var nextFoo = $(this).nextMatching("div.foo");
nextMatching
可以接受各种选择器。我一直很惊讶 next(selector)
没有这样做,但它没有,而且医生对它的作用很清楚,所以..。
我总是可以编写并添加它,尽管如果我这样做并坚持使用已发布的 API,效率会变得非常低。例如,一个 na & iuml; ve next
循环:
jQuery.fn.nextMatching = function(selector) {
var match;
match = this.next();
while (match.length > 0 && !match.is(selector)) {
match = match.next();
}
return match;
};
是 慢一点而不是 nextAll("selector:first")
。这并不奇怪,nextAll
可以把整个事情交给 Sizzle,而 Sizzle 已经完全优化了。上面的循环创建并抛弃了所有类型的临时对象,并且每次都必须重新解析选择器,因此它的速度很慢也就不足为奇了。
当然,我不能只是在最后扔一个 :first
:
jQuery.fn.nextMatching = function(selector) {
return this.nextAll(selector + ":first"); // <== WRONG
};
... 因为虽然它可以用于简单的选择器,比如“ div.foo”,但是如果使用“ any of few”选项,比如“ div.foo,div.bar”,它就会失败。
编辑 : 对不起,应该说: 最后,我可以只使用 .nextAll()
,然后在结果上使用 .first()
,但是那样的话,jQuery 将不得不访问所有的兄弟节点,只是为了找到第一个。我希望它在得到匹配结果时停止,而不是浏览完整的列表,这样它就可以抛弃除第一个结果之外的所有结果。(尽管它似乎发生得很快; 请参阅前面链接的 速度比较中的最后一个测试用例。)
先谢谢你。