Эффективный, лаконичный способ найти следующий соответствующий друг?
Придерживаясь официального API jQuery, существует ли более сжатый, но не менее эффективный способ найти следующего брата элемента, который соответствует данному селектору, кроме использования nextAll
с :first
псевдоclassом?
Когда я говорю об официальном API, я имею в виду не взламывание внутренних компонентов, переход прямо к Sizzle, добавление плагина в микс и т. Д. (Если мне в итоге придется это сделать, пусть будет так, но это не тот вопрос. )
Например, учитывая эту структуру:
- Получить список отмеченных флажков в div с помощью jQuery
- Селектор jQuery: Id заканчивается?
- jQuery получить все div, которые не имеют атрибута classа
- Селектор jQuery для метки флажка
- Разница между CSS-селектором и фильтром jQuery?
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 придется посетить всех братьев и сестер, чтобы найти первый. Я бы хотел, чтобы он остановился, когда он получил матч, а не прошел полный список, чтобы он мог отбросить все результаты, кроме первого. (Хотя, похоже, это происходит очень быстро, см. Последний тестовый пример в сравнении скорости, ранее связанного).
Заранее спасибо.
- Селектор данных jquery
- Как я могу получить соответствующий заголовок таблицы (th) из ячейки таблицы (td)?
- Выбор элементов с определенным цветом фона
- Установите опцию выбора «selected», по значению
- Селектор атрибутов jQuery для нескольких значений
- Почему мой jQuery: not () не работает в CSS?
- jQuery или CSS-селектор, чтобы выбрать все идентификаторы, начинающиеся с некоторой строки
- Как выбрать конкретный элемент формы в 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