Дотримуючись офіційного API jQuery, чи є більш лаконічний, але не менш ефективний спосіб пошуку наступного побратима елемента, який відповідає даному селектору, крім використання 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
in this
(можливо, у click
обробнику, що завгодно) і я хочу знайти наступний div-брат, що відповідає селектору "div.foo", я можу зробити це:
var nextFoo = $(this).nextAll("div.foo:first");
... і це працює (якщо я починаю з "П'ять", наприклад, він пропускає "Шість" і "Сім" і знаходить "Вісім" для мене), але це незграбно, і якщо я хочу відповідати першому з будь-якого з кілька селекторів, стає набагато незграбнішим. (Звичайно, це набагато коротше, ніж був би необроблений цикл 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()
?