2011-08-24 18 views
5

Potrzebuję pobrać pierwszy element.

to zrobić z tym kodem ...

$(element).find('.x').first(); 

Aż Rozumiem, że kod ...

  1. Pobiera wszystkie elementy z element że dopasowane .x,
  2. Usuwa niepotrzebne elementy;

Czy istnieje lepszy sposób to zrobić? Podoba Ci się $.findOne() czy coś takiego?

+0

@Konerak Powiedz mi ... Zadałem pytanie. – daGrevis

+0

Czy istnieje powód, dla którego należy ją zoptymalizować? Czy obecnie trwa to * długo *? –

+0

Uważam, że jest to mała optymalizacja ... ale jeśli mam świetne miejsce, gdzie można zapytać "jak to jest" ... dlaczego nie zoptymalizować? – daGrevis

Odpowiedz

11

Zgodnie z docs jQuery:

Ponieważ: pierwszy to rozszerzenie jQuery i nie jest częścią specyfikacji CSS , kwerendy przy użyciu: po pierwsze nie mogą skorzystać Zwiększenie wydajności zapewniane przez natywną metodę DOM querySelectorAll() . Aby uzyskać najlepszą wydajność podczas używania: najpierw wybierz elementy , najpierw wybierz elementy za pomocą czystego selektora CSS, następnie użyj .filter (": first").

Więc przepisywania wybieraka:

$(element).find('.x').filter(":first") 

lub (ten daje bezpośrednich potomków tylko i będzie szybszy niż .find, chyba że szukasz elementów zagnieżdżonych zbyt)

$(element).children('.x').filter(":first") 

powinien dać Ci lepsze wyniki.


Aktualizacja Po cennych wejść z kingjiv i patrick dw (patrz komentarze), wydaje się, że te dwa są szybsze niż .filter(':first') wbrew zastrzeżeniach doc.

$(element).find('.x').first(); // faster 

$($(element).find('.x')[0]);  // fastest 
+2

+1 za sprawdzenie dokumentów jQuery przed odpowiedzią :) –

+1

+1, ale użyłbym '.first()' zamiast '.filter (": first ")'. Nie jestem pewien, dlaczego dokumentacja sugeruje zamiast tego 'filter',' .first' jest szybsze. ('.first' ma również większy sens dla czytelności, ale to może być tylko preferencja) –

+0

@kingjiv:' filter' korzysta z natywnego 'querySelectorAll()', które zapewnia zwiększenie wydajności. 'first' to zwykły stary styl selekcji, w którym najpierw dostajesz wszystkie elementy i zwracasz pierwszy. Sądzę więc, że przyspieszenie pochodzi z wykonania pojedynczego kroku w przypadku filtra vs. 2 lub więcej w przypadku "pierwszego". – Mrchief

0

ta powinna być lepiej

$(element).find('.x:first'); 
0

Zastosowanie :first selektor:

$(element).find('.x:first') 
0

Lepiej napisać:

$('a:first'); 

co piszesz jest „w 'element', znajdź ".x" i zwróć pierwszą ". I to może być wyrażone jak ten

$('.x:first', element); 
0

jak o użyciu first-child klasy pseudo? jak

$(element).find('.x:first-child') 

Jednak to może generować problemy, czy struktura jest jak

<div> 
    <p></p> 
</div> 
<div> 
    <p></p> 
</div> 

tak właściwie to nie jest to, czego szukasz (jeśli masz na myśli ogólne rozwiązanie). Inne mnetions: pierwszy i to wydaje się być właściwe podejście

+2

To może zwrócić wiele elementów. –

+1

@John: Masz rację! zaktualizowałem swoją odpowiedź, aby wyjaśnić wady tego podejścia i podkreślić, że nie jest to właściwa odpowiedź. – mkk

0

Twój gardłem jest naprawdę .find(), który przeszukuje wszystkie potomków, a nie tylko natychmiastowe dzieci.

Ponadto poszukujesz klasy .x (która używa niestandardowego wyszukiwania jQuery) zamiast identyfikatora lub zmiennej (która używa natywnych metod DOM).

Chciałbym użyć odpowiedzi Mrchiefa, a następnie, jeśli to możliwe, naprawić te dwa wąskie gardła, aby przyspieszyć swój selektor.

0

W ten sposób jest w porządku zgodnie z dokumentacją jQuery lub co najmniej lepiej niż przy użyciu selektora :first.

Możesz wypróbować jako alternatywy .filter(":first") lub uzyskać pierwszy element przy użyciu funkcji dostępu do tablic przy wartości .find() wynik [0].

Również zamiast .find() można zmienić go na adres:

$('.x', element) 

Aby zawęzić wyszukiwanie do .x elementów wewnątrz elementu, intead przeszukiwania całego dokumentu.

2

Szalony, jak się wydaje, w każdym teście wydajności, jaki widziałem, .first() ma lepszą wydajność niż :first.

Jak większość ludzi sugeruje, wydaje się, że korzystanie z $(element).find(".x:first") powinno mieć lepszą wydajność. Jednak w rzeczywistości .first jest szybszy. Nie zajrzałem do wnętrza jquery, aby dowiedzieć się, dlaczego.

http://jsperf.com/jquery-select-first

I widocznie za pomocą [0] a następnie przepakowywania w obiekcie jQuery jest najszybszym:

$($(element).find(".x")[0])

EDIT: Zobacz mrchief za odpowiedź o wyjaśnienie dlaczego. Wygląda na to, że dodali go do dokumentacji.

+0

+1 dla testu porównawczego. :) – daGrevis

0

Można łączyć wywołania $(element) i .find() za pomocą selektora potomnego; Nie mam pewności co do porównania wydajności:

$("#element .x").first().hide(); 
4

Jeśli chcesz mieć to naprawdę szybko, powinieneś użyć rodzimych przeglądarek. Nowoczesne przeglądarki obsługują querySelector[docs]:

var $result; 
if(element.querySelector) { 
    $result = $(element.querySelector('.x')); 
} 
else { 
    $result = $(element).find('.x').first(); 
} 

Użycie jest nieco ograniczona, gdyż działa tylko jeśli element jest pojedynczym elementem, a jeśli przełącznik jest poprawny selektor CSS. Możesz zrobić z tego wtyczkę. Ale wtedy, jeśli weźmiesz pod uwagę wszystkie przypadki, takie jak wiele elementów itd., Prawdopodobnie nie ma już żadnej przewagi.

Tak więc, jeśli masz bardzo konkretny przypadek użycia, może to być przydatne, jeśli nie, trzymać się jQuery.

Aktualizacja: Okazuje się, dzięki czemu wtyczki jest jeszcze szybsze: jsPerf benchmark

(function($) { 
    $.fn.findOne = function(selector) { 
     try { 
      var element, i = 0, l = this.length; 
      while(i < l && (element = this[i].querySelector(selector)) === null) { 
       i++; 
      } 
      return $(element); 
     } 
     catch(e) { 
      return this.find(selector).first(); 
     } 
    }; 
}(jQuery)); 

Jak to działa:

The iteracje wtyczek ponad wybranych elementów DOM i wzywa querySelector na każdym z nich. Po znalezieniu elementu pętla zakończy się i zwróci znaleziony element. Istnieją dwa powody, może wystąpić wyjątek:

  • przeglądarek nie obsługuje querySelector
  • Selektor nie jest czystym selektor CSS

W obu przypadkach wtyczki spadnie z powrotem do korzystania normalny Metoda jQuery.

+1

Zastanawiam się, dlaczego wersja wtyczki jest szybsza niż bezpośrednie wywołanie "document.querySelector". – user113716

+0

@patrick: Też się nad tym zastanawiałem, pomyślałem, że może wtyczka całkowicie zawiedzie (nie robi nic, ale myślę, że to działa;)). Domyślam się, że nieco droższe jest wyszukiwanie w katalogu głównym dokumentu. I FWIW, wydaje się, że nie ma różnicy w Chrome. –

+0

Taa, to jedyna rzecz, o której też mogłem pomyśleć.Zaskakujące, ponieważ wtyczka musi wykonywać wiele połączeń. Może 'document.body.querySelector' będzie działać lepiej. – user113716