jQuery a document.querySelectorAll

161

Kilkakrotnie słyszałem, że najsilniejszym atutem jQuery jest sposób, w jaki wykonuje zapytania i manipuluje elementami w DOM: możesz używać zapytań CSS do tworzenia złożonych zapytań, które byłyby bardzo trudne do wykonania w zwykłym javascript. Jednak o ile wiem, ten sam wynik można osiągnąć za pomocą document.querySelectorlub document.querySelectorAll, które są obsługiwane w przeglądarce Internet Explorer 8 i nowszych.

Zatem pytanie brzmi: po co „ryzykować” narzut jQuery, skoro jego najsilniejszy atut można osiągnąć za pomocą czystego JavaScript?

Wiem, że jQuery ma więcej niż tylko selektory CSS, na przykład AJAX między przeglądarkami, fajne dołączanie zdarzeń itp. Ale jego część z zapytaniami jest bardzo dużą częścią siły jQuery!

jakieś pomysły?

Joel_Blum
źródło
4
(1) Przechodzenie / modyfikacja DOM jest znacznie szybsza i łatwiejsza dzięki jQuery. (2) Dodaje własne selektory, które nie będą działać w querySelectormetodach. (3) Wykonywanie połączeń AJAX jest znacznie szybsze i łatwiejsze dzięki jQuery. (4) Wsparcie w IE6 +. Jestem pewien, że jest o wiele więcej punktów, które można by poruszyć.
James Allardice,
12
(5) ... skrót $ () dla leniwych maszynistek jest koniecznością.
Dexter Huinda,
4
łatwiej tak, dlaczego szybciej? jQuery tłumaczy się na zwykły javascript, o ile wiem ...
Joel_Blum
4
@ JamesAllardice - „cały ten bałagan” dla XMLHttpRequest w różnych przeglądarkach to może 30 wierszy kodu , który napiszesz raz i umieścisz w swojej własnej bibliotece.
RobG,
6
@RobG - Tak, nie mówię, że po prostu używaj jQuery, jeśli tylko do tego próbujesz. To tylko jedna z korzyści. Jeśli potrzebujesz łatwego przechodzenia przez DOM, AJAX i wszystko querySelectorAll, czego potrzebujesz do pracy w starszych przeglądarkach, jQuery jest oczywistym wyborem. Nie mówię, że powinieneś tego używać w ten sposób .
James Allardice,

Odpowiedzi:

127

document.querySelectorAll() ma kilka niespójności między przeglądarkami i nie jest obsługiwany w starszych przeglądarkach To prawdopodobnie nie będzie już powodować żadnych problemów w dzisiejszych czasach . Ma bardzo nieintuicyjny mechanizm określania zakresu i kilka innych niezbyt przyjemnych funkcji . Również w przypadku javascript praca z zestawami wyników tych zapytań jest trudniejsza, co w wielu przypadkach możesz chcieć zrobić. jQuery udostępnia funkcje do pracy nad nimi jak: filter(), find(), children(), parent(), map(), not()i kilka innych. Nie wspominając o zdolności jQuery do pracy z selektorami pseudoklas.

Jednak nie uważałbym tych rzeczy za najsilniejsze cechy jQuery, ale inne rzeczy, takie jak „praca” nad domem (zdarzenia, stylizacja, animacja i manipulacja) w sposób zgodny z różnymi przeglądarkami lub interfejs Ajax .

Jeśli chcesz tylko silnika selektora z jQuery, możesz użyć tego, którego używa jQuery: Sizzle W ten sposób masz moc silnika jQuerys Selector bez przykrych kosztów.

EDYCJA: Tak dla przypomnienia, jestem wielkim fanem waniliowego JavaScript. Niemniej jednak faktem jest, że czasami potrzebujesz 10 linii JavaScript, w których możesz napisać 1 wiersz jQuery.

Oczywiście trzeba być zdyscyplinowanym, aby nie pisać jQuery w ten sposób:

$('ul.first').find('.foo').css('background-color', 'red').end().find('.bar').css('background-color', 'green').end();

Jest to niezwykle trudne do odczytania, podczas gdy to drugie jest całkiem jasne:

$('ul.first')
   .find('.foo')
      .css('background-color', 'red')
.end()
   .find('.bar')
      .css('background-color', 'green')
.end();

Równoważny JavaScript byłby znacznie bardziej złożony, co ilustruje powyższy pseudokod:

1) Znajdź element, rozważ wzięcie całego elementu lub tylko pierwszego.

// $('ul.first')
// taking querySelectorAll has to be considered
var e = document.querySelector("ul.first");

2) Iteruj po tablicy węzłów potomnych za pomocą niektórych (prawdopodobnie zagnieżdżonych lub rekurencyjnych) pętli i sprawdź klasę (lista klas nie jest dostępna we wszystkich przeglądarkach!)

//.find('.foo')
for (var i = 0;i<e.length;i++){
     // older browser don't have element.classList -> even more complex
     e[i].children.classList.contains('foo');
     // do some more magic stuff here
}

3) zastosuj styl css

// .css('background-color', 'green')
// note different notation
element.style.backgroundColor = "green" // or
element.style["background-color"] = "green"

Ten kod byłby co najmniej dwa razy większy niż wiersze kodu, które piszesz za pomocą jQuery. Należy również wziąć pod uwagę problemy z różnymi przeglądarkami, które mogą zagrozić znacznej przewadze szybkości (poza niezawodnością) kodu natywnego.

Christoph
źródło
33
Jakie niespójności querySelectorAllwystępują między przeglądarkami? I jak użycie jQuery mogłoby rozwiązać ten problem, skoro jQuery używa, querySelectorAll gdy jest dostępne?
3
To prawda, jedna linia kodu może zawierać łańcuchy niekończących się kodów, które mogą być bardzo irytujące podczas debugowania.
Dexter Huinda,
1
"2) iteruj po tablicy węzłów potomnych za pomocą jakichś (prawdopodobnie zagnieżdżonych lub rekurencyjnych) pętli i sprawdź klasę" << To totalna bzdura. Możesz użyć querySelectorAll w elemencie w poprzednim kroku.
Vanuan,
5
@Vanuan może to nie być konieczne, ale gdybyś dokładnie przeczytał moją odpowiedź, zauważyłbyś, że querySelector ma poważny problem z zakresem, który może dać ci wiele fałszywych alarmów, gdy zostanie użyty w proponowany sposób. Niemniej jednak, chociaż możesz głosować za lub przeciw z jakiegoś dziwacznego powodu, myślę, że nie jest to powód do używania wulgarnego języka.
Christoph,
2
@Christoph Ponieważ jest to łatwe, dodałem kompatybilność z IE8 i nowszymi. Wciąż ogromne zalety prędkości (5-20 razy). To, że kod będzie działał wolniej w starej przeglądarce, takiej jak IE8, to tylko błędne założenie.
Pascalius
60

Jeśli optymalizujesz swoją stronę dla IE8 lub nowszej wersji, powinieneś naprawdę rozważyć, czy potrzebujesz jquery, czy nie. Nowoczesne przeglądarki mają wiele zasobów natywnie dostarczanych przez jquery.

Jeśli zależy Ci na wydajności, możesz uzyskać niesamowite korzyści w zakresie wydajności (2-10 szybciej), używając natywnego javascript: http://jsperf.com/jquery-vs-native-selector-and-element-style/2

Przekształciłem div-tagcloud z jquery na natywny javascript (kompatybilny z IE8 +), wyniki są imponujące. 4 razy szybciej przy niewielkim obciążeniu.

                    Number of lines       Execution Time                       
Jquery version :        340                    155ms
Native version :        370                    27ms

You Might Not Need Jquery zapewnia naprawdę przyjemny przegląd, w którym metody natywne zastępują daną wersję przeglądarki.

http://youmightnotneedjquery.com/


Dodatek: Dalsze porównania szybkości, w jaki sposób metody natywne konkurują z jQuery

Pascalius
źródło
ładny przegląd, chociaż niektóre przykłady kodu są błędne ... Np. $(el).find(selector)nie jest równy, el.querySelectorAll(selector)a wydajność metod natywnych jest często dość okropna: stackoverflow.com/q/14647470/1047823
Christoph
@Christoph Czy możesz wyjaśnić, dlaczego uważasz, że metody są różne? Oczywiście istnieją skrajne przypadki, w których jquery może działać lepiej, ale nie widziałem ani jednego dla DOM-Manipulation.
Pascalius
1
Nie ma potrzeby dalszego rozwijania, po prostu przeczytaj moją odpowiedź, spójrz na skrzypce i artykuł, do którego utworzyłem łącze. Ponadto (przynajmniej atm) większość natywnych metod Array ma gorszą prędkość w porównaniu z naiwną implementacją js (tak jak podlinkowałem w pytaniu w moim pierwszym komentarzu). I to nie są przypadki skrajne, ale raczej standardowy przypadek. Ale znowu, głównym celem tego pytania nie była prędkość.
Christoph,
2
@Christoph Oczywiście te metody nie są w 100% równe, a jquery często zapewnia większą wygodę. Zaktualizowałem odpowiedź, aby pokazać, że to tylko przypadek skrajny. Właściwie nie mogłem znaleźć żadnego innego przypadku, w którym jquery działało lepiej. Nie ma głównego tematu pytania.
Pascalius
+1 Doskonała odpowiedź! Powoli zastępowałem stary kod jQuery surowym kodem JavaScript w ciągu ostatnich 4 lub 5 lat, gdziekolwiek i kiedykolwiek było to możliwe .. Oczywiście jQuery jest świetny do niektórych rzeczy i używam go do tych rzeczy, gdy czuję, że mam solidne korzyści.
Tak, Barry,
13

Aby zrozumieć, dlaczego jQuery jest tak popularny, ważne jest, aby zrozumieć, skąd pochodzimy!

Około dekady temu najpopularniejszymi przeglądarkami były IE6, Netscape 8 i Firefox 1.5. W tamtych czasach poza tym nie było wielu sposobów wybierania elementu z DOM w różnych przeglądarkach Document.getElementById().

Tak więc, kiedy jQuery został wydany w 2006 roku , był całkiem rewolucyjny. Wtedy jQuery wyznaczyło standard łatwego wybierania / zmiany elementów HTML i wyzwalania zdarzeń, ponieważ jego elastyczność i obsługa przeglądarki były bezprecedensowe.

Teraz, ponad dziesięć lat później, wiele funkcji, które sprawiły, że jQuery stało się tak popularne, zostało włączonych do standardu javaScript:

Nie były one ogólnie dostępne w 2005 roku. Fakt, że są dzisiaj, oczywiście nasuwa pytanie, dlaczego w ogóle powinniśmy używać jQuery. I rzeczywiście, ludzie coraz częściej zastanawiają się, czy w ogóle powinniśmy używać jQuery .

Więc jeśli myślisz, że rozumiesz JavaScript na tyle dobrze, aby obejść się bez jQuery, zrób to! Nie czuj się zmuszony do korzystania z jQuery tylko dlatego, że robi to tak wielu innych!

John Slegers
źródło
7

Dzieje się tak, ponieważ jQuery może znacznie więcej niż querySelectorAll.

Przede wszystkim jQuery (aw szczególności Sizzle) działa w starszych przeglądarkach, takich jak IE7-8, które nie obsługują selektorów CSS2.1-3.

Ponadto Sizzle (który jest silnikiem selektora stojącym za jQuery) oferuje wiele bardziej zaawansowanych instrumentów selektora, takich jak :selectedpseudoklasa, zaawansowany :not()selektor, bardziej złożoną składnię, taką jak in $("> .children")i tak dalej.

I robi to bezbłędnie na różnych przeglądarkach, oferując wszystko, co może zaoferować jQuery (wtyczki i API).

Tak, jeśli myślisz, że możesz polegać na prostych selektorach klas i identyfikatorów, jQuery to dla Ciebie za dużo i zapłacisz przesadną zapłatę. Ale jeśli tego nie robisz i chcesz wykorzystać wszystkie zalety jQuery, użyj go.

MaxArt
źródło
7

Silnik selektora Sizzle jQuery może użyć, querySelectorAlljeśli jest dostępny. Wygładza również niespójności między przeglądarkami, aby uzyskać jednolite wyniki. Jeśli nie chcesz używać całego jQuery, możesz po prostu osobno użyć Sizzle. To dość fundamentalne koło do wymyślenia.

Oto kilka propozycji ze źródła, które pokazują, jakie rzeczy sortuje dla Ciebie jQuery (w / Sizzle):

Tryb dziwactwa Safari:

if ( document.querySelectorAll ) {
  (function(){
    var oldSizzle = Sizzle,
      div = document.createElement("div"),
      id = "__sizzle__";

    div.innerHTML = "<p class='TEST'></p>";

    // Safari can't handle uppercase or unicode characters when
    // in quirks mode.
    if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
      return;
    }

Jeśli ten strażnik zawiedzie, użyje wersji Sizzle, która nie jest ulepszona querySelectorAll. W dalszej części znajdują się specyficzne uchwyty niespójności w IE, Operze i przeglądarce Blackberry.

  // Check parentNode to catch when Blackberry 4.6 returns
  // nodes that are no longer in the document #6963
  if ( elem && elem.parentNode ) {
    // Handle the case where IE and Opera return items
    // by name instead of ID
    if ( elem.id === match[3] ) {
      return makeArray( [ elem ], extra );
    }

  } else {
    return makeArray( [], extra );
  }

A jeśli wszystko inne zawiedzie, zwróci wynik oldSizzle(query, context, extra, seed).

KGZM
źródło
6

Jeśli chodzi o łatwość utrzymania kodu, istnieje kilka powodów, dla których warto trzymać się powszechnie używanej biblioteki.

Jedną z głównych jest to, że są dobrze udokumentowane i mają społeczności takie jak ... powiedzmy ... stackexchange, gdzie można znaleźć pomoc przy bibliotekach. Dzięki niestandardowej bibliotece kodowanej masz kod źródłowy i być może dokument instruktażowy, chyba że programiści spędzili więcej czasu na dokumentowaniu kodu niż na jego pisaniu, co jest rzadkością.

Pisanie własnej biblioteki może Ci pomóc pomóc, ale stażysta siedzący przy sąsiednim biurku może mieć łatwiejsze opanowanie czegoś takiego jak jQuery.

Nazwij to efektem sieci, jeśli chcesz. Nie oznacza to, że kod będzie lepszy w jQuery; tylko dlatego, że zwięzły charakter kodu ułatwia zrozumienie ogólnej struktury programistom na wszystkich poziomach umiejętności, choćby dlatego, że w przeglądanym pliku jest widocznych od razu więcej funkcjonalnego kodu. W tym sensie 5 linii kodu jest lepsze niż 10.

Podsumowując, widzę główne zalety jQuery jako zwięzły kod i wszechobecność.

Dom Day
źródło
6

Oto porównanie, jeśli chcę zastosować ten sam atrybut, np. Ukryć wszystkie elementy klasy „moja-klasa”. To jeden z powodów, dla których warto używać jQuery.

jQuery:

$('.my-class').hide();

JavaScript:

var cls = document.querySelectorAll('.my-class');
for (var i = 0; i < cls.length; i++) {
    cls[i].style.display = 'none';
}

Z jQuery już tak popularnym, powinni byli sprawić, by document.querySelector () zachowywała się tak jak $ (). Zamiast tego document.querySelector () wybiera tylko pierwszy pasujący element, co czyni go użytecznym tylko w połowie.

Steven
źródło
4
Zrobiłbym tutaj .forEach.
Phillip Senn
Cóż, zawsze możesz wybrać łatwiejszą trasę document.querySelectorAll('.my-class').forEach(el => el.style.display = 'none');. Mimo to, nawet jeśli jest krótszy, natywny pod względem wydajności jest zawsze lepszy.
Alain Cruz
Z punktu widzenia użytkownika wszystko, co dzieje się w czasie krótszym niż 0,1 sekundy, dzieje się natychmiast. Dlatego natywny jest nawet szybszy, lepszy tylko w przypadku, gdy implementacja jQuery wolniejsza niż 0,1 sek. W rzeczywistych zastosowaniach nigdy tak nie jest.
yurin
3

jak mówi oficjalna strona: „jQuery: pisz mniej, rób więcej, biblioteka JavaScript”

spróbuj przetłumaczyć następujący kod jQuery bez żadnej biblioteki

$("p.neat").addClass("ohmy").show("slow");
simon xu
źródło
1
Zgadzam się z tym, ale co z czytelnością? jak udokumentować długie linie kodu, w których dzieje się wiele niezwiązanych z nimi rzeczy? Jak możesz debugować takie potworności?
Joel_Blum,
@ user1032663 to kwestia konwencji dokumentacji.
Christoph,
1
Alternatywą dla jQuery (lub jakiejkolwiek „popularnej” biblioteki, którą wybierzesz) nie jest pisanie wszystkiego od zera, ale użycie biblioteki, która odpowiada Twoim celom i jest dobrze napisana. Być może sam napisałeś części lub wybrałeś bibliotekę modułową, taką jak MyLibrary, aby zawierała tylko to, czego potrzebujesz.
RobG,
2
Przykład, który wybrałeś, tak naprawdę nie potwierdza twojego punktu widzenia: chodzi o poszukiwanie różnic w prowincji „selektor”. addClass()i show()tak naprawdę nie licz. A jeśli chodzi o $('p.neat'), możesz rzucić okiem na querySelector / All.
kumarharsh
document.querySelectorAll('p.neat').forEach(p=>p.classList.add('ohmy'));a CSS zajmie się resztą. Nieco dłuższy kod, ale znacznie wydajniejszy. Oczywiście jego rozwiązanie nie było tak dostępne w czasach Legacy IE. Część „Zrób więcej” jest ironiczna. jQuery potrzebuje około stu wierszy kodu, aby coś znaleźć, więc robienie więcej nie zawsze jest produktywne.
Manngo
2

Myślę, że prawdziwa odpowiedź jest taka, że ​​jQuery zostało opracowane dużo wcześniej querySelector/querySelectorAll udostępnieniem go we wszystkich głównych przeglądarkach.

Pierwsze wydanie jQuery miało miejsce w 2006 roku . W rzeczywistości nawet jQuery nie był pierwszym, który zaimplementował selektory CSS .

IE była ostatnią implementowaną przeglądarkąquerySelector/querySelectorAll . Jego ósma wersja została wydana w 2009 roku .

Więc teraz selektory elementów DOM nie są już najmocniejszą stroną jQuery. Jednak wciąż ma wiele dodatków w rękawie, takich jak skróty do zmiany zawartości css i html elementu, animacje, powiązanie zdarzeń, ajax.

Vanuan
źródło
1

Stare pytanie, ale pół dekady później warto do niego wrócić. Tutaj omawiam tylko aspekt selektora jQuery.

document.querySelector[All]jest obsługiwany przez wszystkie obecne przeglądarki, aż do IE8, więc kompatybilność nie jest już problemem. Nie znalazłem również żadnych problemów z wydajnością, o których mógłbym mówić (miał być wolniejszy niż document.getElementById, ale moje własne testy sugerują, że jest nieco szybszy).

Dlatego jeśli chodzi o bezpośrednie manipulowanie elementem, powinien być preferowany niż jQuery.

Na przykład:

var element=document.querySelector('h1');
element.innerHTML='Hello';

jest znacznie lepszy:

var $element=$('h1');
$element.html('hello');

Aby w ogóle cokolwiek zrobić, jQuery musi przejść przez sto linii kodu (kiedyś prześledziłem kod, taki jak powyższy, aby zobaczyć, co właściwie jQuery z nim robi). To z pewnością strata czasu dla wszystkich.

Innym znaczącym kosztem jQuery jest to, że opakowuje wszystko w nowy obiekt jQuery. Ten narzut jest szczególnie marnotrawny, jeśli musisz ponownie rozpakować obiekt lub użyć jednej z metod obiektu, aby poradzić sobie z właściwościami, które są już widoczne w oryginalnym elemencie.

Jednak zaletą jQuery jest sposób, w jaki obsługuje kolekcje. Jeśli wymaganiem jest ustawienie właściwości wielu elementów, jQuery ma wbudowaną eachmetodę, która pozwala na coś takiego:

var $elements=$('h2');  //  multiple elements
$elements.html('hello');

Aby to zrobić z Vanilla JavaScript wymagałoby czegoś takiego:

var elements=document.querySelectorAll('h2');
elements.forEach(function(e) {
    e.innerHTML='Hello';
});

co niektórzy uważają za zniechęcające.

Selektory jQuery również są nieco inne, ale nowoczesne przeglądarki (z wyjątkiem IE8) nie przyniosą większych korzyści.

Z reguły odradzam używanie jQuery do nowych projektów:

  • jQuery to zewnętrzna biblioteka dodająca do kosztów ogólnych projektu i do Twojej zależności od stron trzecich.
  • Funkcja jQuery jest bardzo droga, jeśli chodzi o przetwarzanie.
  • jQuery narzuca metodologię, której należy się nauczyć i która może konkurować z innymi aspektami kodu.
  • jQuery wolno udostępnia nowe funkcje w JavaScript.

Jeśli żadne z powyższych nie ma znaczenia, rób, co chcesz. Jednak jQuery nie jest już tak ważny dla tworzenia aplikacji wieloplatformowych, jak kiedyś, ponieważ nowoczesny JavaScript i CSS idą o wiele dalej niż kiedyś.

Nie wspomina się o innych cechach jQuery. Myślę jednak, że oni również potrzebują bliższego przyjrzenia się.

Manngo
źródło
1
Twoja składnia nie jest nawet poprawna, nie wspominając o innych błędnych rzeczach, takich jak „powolne ujawnianie nowych funkcji w JavaScript” Zadaniem JQuery nie jest nawet udostępnianie nowych funkcji, ale ułatwienie manipulowania DOM i robienie prostych rzeczy, które mogą być jak 10 linii w Javascript. Cały Twój komentarz po prostu nie ma sensu i zawiera wiele niewłaściwych rzeczy. Rozważ jego ulepszenie.
Boy pro,
@Boypro Dziękuję za komentarz, ale także jest pełen błędów. Może chciałbyś się podzielić tym, co w mojej odpowiedzi tak cię obraża. Co jest „nawet nie w porządku”. Co więcej, możesz chcieć wnieść własną odpowiedź. Pytanie dotyczy kosztu korzystania z jQuery, skoro zwykły JavaScript potrafi tyle. Rozważ odpowiedź.
Manngo,
0
$ ("# id") a document.querySelectorAll ("# id")

Umowa polega na tym, że funkcja $ () tworzy tablicę, a następnie dzieli ją za Ciebie, ale za pomocą funkcji document.querySelectorAll () tworzy tablicę i musisz ją podzielić.


źródło
0

Tylko komentarz na ten temat, gdy używasz Material Design Lite, selektor jQuery z jakiegoś powodu nie zwraca właściwości Material Design.

Dla:

<div class="logonfield mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
        <input class="mdl-textfield__input" type="text" id="myinputfield" required>
        <label class="mdl-textfield__label" for="myinputfield">Enter something..</label>
      </div>

To działa:

document.querySelector('#myinputfield').parentNode.MaterialTextfield.change();

To nie:

$('#myinputfield').parentNode.MaterialTextfield.change();
Ashvin Bhuttoo
źródło