Эффективный, лаконичный способ найти следующий соответствующий друг?

Придерживаясь официального API jQuery, существует ли более сжатый, но не менее эффективный способ найти следующего брата элемента, который соответствует данному селектору, кроме использования nextAll с :first псевдоclassом?

Когда я говорю об официальном API, я имею в виду не взламывание внутренних компонентов, переход прямо к Sizzle, добавление плагина в микс и т. Д. (Если мне в итоге придется это сделать, пусть будет так, но это не тот вопрос. )

Например, учитывая эту структуру:

 
One
Two
Three
Four
Five
Six
Seven
Eight

Если у меня есть div в this (возможно, в обработчике click , что угодно) и вы хотите найти следующий div div, который соответствует селектору div.foo, я могу сделать это:

 var nextFoo = $(this).nextAll("div.foo:first"); 

… и он работает (если я начинаю с «Пятерки», например, он пропускает «Шесть» и «Семь» и называет «восьмерку» для меня), но он неуклюж, и если я хочу сопоставить первый из любых несколько селекторов, он становится намного clunkier. (Конечно, это намного более сжато, чем сырой цикл DOM …)

Я в основном хочу:

 var nextFoo = $(this).nextMatching("div.foo"); 

… где 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; }; 

заметно медленнее, чем nextAll("selector:first") . И это не удивительно, nextAll может передать все это Sizzle, и Sizzle был тщательно оптимизирован. Наивный цикл выше создает и выбрасывает всевозможные временные объекты и должен каждый раз перебирать селектор, и не удивительно, что он медленный.

И, конечно, я не могу просто бросить :first в конце:

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

… потому что, хотя это будет работать с простыми селекторами типа «div.foo», он не сработает с «любой из нескольких» опций, о которых я говорил, например, «div.foo, div.bar».

Редактировать : Извините, должен был сказать: Наконец, я мог бы просто использовать .nextAll() а затем использовать .first() для результата, но тогда jQuery придется посетить всех братьев и сестер, чтобы найти первый. Я бы хотел, чтобы он остановился, когда он получил матч, а не прошел полный список, чтобы он мог отбросить все результаты, кроме первого. (Хотя, похоже, это происходит очень быстро, см. Последний тестовый пример в сравнении скорости, ранее связанного).

Заранее спасибо.

Вы можете передать множественный селектор в .nextAll() и использовать .first() для результата, например:

 var nextFoo = $(this).nextAll("div.foo, div.something, div.else").first(); 

Редактирование: просто для сравнения, здесь он добавлен в тестовый набор: http://jsperf.com/jquery-next-loop-vs-nextall-first/2 Этот подход намного быстрее, потому что это простая комбинация передачи .nextAll() когда это возможно, отключаться до собственного кода (каждый текущий браузер) и просто принимать первый из набора результатов …. быстрее, чем любой цикл, который вы можете делать исключительно в JavaScript.

Как насчет использования first метода:

 jQuery.fn.nextMatching = function(selector) { return this.nextAll(selector).first(); } 

Изменить, обновить

Использование селектора Next Siblings (“prev ~ siblings”)

 jQuery.fn.nextMatching = function nextMatchTest(selector) { return $("~ " + selector, this).first() }; 

http://jsperf.com/jquery-next-loop-vs-nextall-first/10

 jQuery.fn.nextMatching = function nextMatchTest(selector) { return $("~ " + selector, this).first() }; var nextFoo = $("div:first").nextMatchTest("div.foo"); console.log(nextFoo) 
  
One
Two
Three
Four
Five
Six
Seven
Eight
  • Как определить, работает ли браузер Chrome с помощью jQuery?
  • Селектор jQuery для метки флажка
  • Имя атрибута jQuery содержит
  • Как получить доступ к свойствам стиля псевдоэлементов с помощью jQuery?
  • addID в jQuery?
  • Что такое fastest children () или find () в jQuery?
  • Изменение CSS-элемента дочернего элемента при зависании родительского элемента
  • поиск jQuery и контекст
  • jQuery получить все div, которые не имеют атрибута classа
  • Более чистый способ выбора нескольких возможных значений атрибутов?
  • Как работают PrimeFaces Selectors как в update = "@ (. MyClass)"?
  • Давайте будем гением компьютера.