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

Придерживаясь официального 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
  • jQuery .bind () vs. .on ()
  • : nth-of-type () в jQuery / Sizzle?
  • jQuery hasClass () - проверьте несколько classов
  • jQuery выбрать по classу VS выбрать по атрибуту
  • jQuery выбрать все, кроме первого
  • Какие селектора CSS3 действительно поддерживают jQuery, например: nth-last-child ()?
  • Найти все элементы на основе ids с помощью regex в селекторе jQuery
  • Как работают PrimeFaces Selectors как в update = "@ (. MyClass)"?
  • Выбрать элемент по точному соответствию его содержимому
  • Как я могу получить идентификатор элемента с помощью jQuery?
  • Каков самый быстрый способ выбора элементов-потомков в jQuery?
  • Давайте будем гением компьютера.