Придерживаясь официального 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");
... и это работает (например, если я начинаю с "Five", оно пропускает "Six" и "Seven" и находит для меня "Eight"), но это неуклюже, и если я хочу соответствовать первому из любого из нескольких селекторов, он становится намного более грубым. (Конечно, это много более кратко, чем был бы необработанный цикл 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 придется посетить всех братьев и сестер, чтобы найти первый. Я бы хотел, чтобы он остановился, когда получит совпадение, а не просмотрел весь список, чтобы он мог отбросить все результаты, кроме первого. (Хотя, кажется, это происходит действительно быстро; см. Последний тестовый пример в сравнении скорости , связанном ранее.)
Заранее спасибо.