找到下一个匹配的兄弟姐妹的高效,简洁的方法?

T.J*_*der 75 jquery jquery-selectors

坚持官方的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>
Run Code Online (Sandbox Code Playgroud)

如果我有一个divin this(也许在一个click处理程序中,无论如何)并且想要找到与选择器"div.foo"匹配的下一个兄弟div,我可以这样做:

var nextFoo = $(this).nextAll("div.foo:first");
Run Code Online (Sandbox Code Playgroud)

...它有效(例如,如果我从"五"开始,它跳过"六"和"七"并为我找到"八"),但它很笨重,如果我想匹配任何一个的第一个几个选择器,它变得更加笨拙.(当然,这是一个很多更简洁比原始DOM循环将是...)

我基本上想要:

var nextFoo = $(this).nextMatching("div.foo");
Run Code Online (Sandbox Code Playgroud)

......哪里nextMatching可以接受全系列的选择器.我总是感到惊讶,next(selector)不这样做,但事实并非如此,并且文档清楚它的作用,所以......

我可以随时编写并添加它,但如果我这样做并坚持使用已发布的API,事情会变得非常低效.例如,一个天真的next循环:

jQuery.fn.nextMatching = function(selector) {
    var match;

    match = this.next();
    while (match.length > 0 && !match.is(selector)) {
        match = match.next();
    }
    return match;
};
Run Code Online (Sandbox Code Playgroud)

...... 明显nextAll("selector:first").这并不奇怪,nextAll可以把整个事情交给Sizzle,而Sizzle已经彻底优化了.上面的天真循环创建并丢弃各种临时对象,并且每次都必须重新解析选择器,没有什么大惊喜它很慢.

当然,我不能只是抛出一个:first结尾:

jQuery.fn.nextMatching = function(selector) {
    return this.nextAll(selector + ":first"); // <== WRONG
};
Run Code Online (Sandbox Code Playgroud)

...因为虽然这将适用于像"div.foo"这样的简单选择器,但它会因为我所谈到的"任何几个"选项而失败,比如说"div.foo,div.bar".

编辑:对不起,应该说:最后,我可以使用.nextAll()然后使用.first()结果,但然后jQuery将不得不访问所有的兄弟姐妹只是为了找到第一个.我希望它在获得匹配时停止而不是通过完整列表只是因为它可以丢弃所有结果,但第一个.(虽然它似乎发生得非常快;请参阅之前链接的速度比较中的最后一个测试用例.)

提前致谢.

Nic*_*ver 92

您可以通过一个多选择.nextAll()和使用.first()的结果,就像这样:

var nextFoo = $(this).nextAll("div.foo, div.something, div.else").first();
Run Code Online (Sandbox Code Playgroud)

编辑:为了比较,这里它被添加到测试套件:http://jsperf.com/jquery-next-loop-vs-nextall-first/2 这种方法快得多,因为它是一个简单的组合处理.nextAll()选择关闭到本机代码时可能(每当前的浏览器),只是采取的第一个结果集的.... 方式比任何循环,你可以在JavaScript纯粹做得更快.

  • @Mark - `.eq(0)`将是绝对最快的,因为[什么是`.first()`调用](https://github.com/jquery/jquery/blob/1.5/src/core.js #L263-265),但与其他所有内容相比的差异是无穷小的,所以在这种情况下我会选择更易读的代码.话虽这么说,我的例子不是插件......如果人们不直接使用它,一定要用`.eq(0)`. (5认同)
  • 哪个更快'.first()'或'.eq(0)'? (2认同)

lon*_*day 9

使用first方法怎么样:

jQuery.fn.nextMatching = function(selector) {
    return this.nextAll(selector).first();
}
Run Code Online (Sandbox Code Playgroud)