Придерживаясь официального 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>
Если у меня есть div
в this
(возможно, в обработчике click
, что бы то ни было) и хотите найти следующий дочерний div, соответствующий селектору div.foo, я могу сделать это:
var nextFoo = $(this).nextAll("div.foo:first");
... и он работает (если я начинаю с "Пятерки", например, он пропускает "Шесть" и "Семь" и называет "Восьмерка" для меня), но он неуклюж, и если я хочу сопоставить первый любого из нескольких селекторов, он становится намного clunkier. (Конечно, это лот более кратким, чем сырой цикл 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 полностью оптимизирован. Верхняя петля na & iuml; ve выше создает и выбрасывает всевозможные временные объекты и должна каждый раз перебирать селектор, и не удивительно, что это замедляется.
И, конечно, я не могу просто выбросить :first
в конец:
jQuery.fn.nextMatching = function(selector) {
return this.nextAll(selector + ":first"); // <== WRONG
};
... потому что, хотя это будет работать с простыми селекторами, такими как "div.foo", он будет терпеть неудачу с опцией "любой из нескольких", о которой я говорил, например, "div.foo, div.bar".
Изменить: Извините, должен был сказать: Наконец, я мог бы просто использовать .nextAll()
, а затем использовать .first()
для результата, но тогда jQuery придется посетить всех братьев и сестер только для найти первый. Я бы хотел, чтобы он остановился, когда он получил матч, а не прошел полный список, чтобы он мог отбросить все результаты, кроме первого. (Хотя это происходит очень быстро, см. Последний тестовый пример в сравнение скорости, связанный ранее.)
Спасибо заранее.