Co zwracają metody querySelectorAll i getElementsBy *?


151

Czy getElementsByClassName(i podobne funkcje, takie jak getElementsByTagNamei querySelectorAll) działają tak samo, getElementByIdczy zwracają tablicę elementów?

Pytam o to, że próbuję zmienić styl wszystkich używanych elementów getElementsByClassName. Zobacz poniżej.

//doesn't work
document.getElementsByClassName('myElement').style.size = '100px';

//works
document.getElementById('myIdElement').style.size = '100px';

37
Wskazówka jest w nazwie: getElementsByClassName()implikuje liczbę mnogą, podczas gdy getElementById()implikuje pojedynczy element elementowy.
David mówi, że przywróć Monikę

1
Rozumiem, po prostu nie miało dla mnie sensu, że nie można zmienić wszystkich elementów o tej nazwie klasy za pomocą powyższego kodu, zamiast wykonywać pętlę przez tablicę. sposób jquery jest znacznie lepszy, byłem po prostu ciekawy sposobu js
dmo

1
Może się też przydać: stackoverflow.com/questions/3871547/ ...
kapa

Odpowiedzi:


152

Twój getElementById()kod działa, ponieważ identyfikatory muszą być unikalne, dlatego funkcja zawsze zwraca dokładnie jeden element (lub nulljeśli go nie znaleziono).

Jednakże getElementsByClassName(), querySelectorAll(), i inne getElementsBy*metody zwrócić zbiór macierzy podobne elementy. Powtarzaj to tak, jak w przypadku prawdziwej tablicy:

var elems = document.getElementsByClassName('myElement');
for(var i = 0; i < elems.length; i++) {
    elems[i].style.size = '100px';
}

Jeśli wolisz coś krótszego, rozważ użycie jQuery :

$('.myElement').css('size', '100px');

1
Czy to dotyczy również tego, <iframe>co jest również częścią Twojej domeny
JMASTER B

3
Jest rok 2018 ... Po prostu utwórz funkcję opakowującą querySelectorAll()i możesz mieć ładny, krótki kod bez dużej, starej szkoły zależności. qSA(".myElement").forEach(el => el.style.size = "100px")Może niech opakowanie otrzyma oddzwonienie. qSA(".myElement", el => el.style.size = "100px")

2
„Jeśli wolisz coś krótszego, rozważ dodanie do swojego projektu ogromnej biblioteki” Wiem, że rok 2012 był innym czasem, ale nawet wtedy uznałbym to za niedorzeczne.
CoryCoolguy

1
Powtarzaj to tak, jak w przypadku prawdziwej tablicy… Ostrożnie, getElementsByClassName zwraca aktywną listę NodeList, która może zostać nieoczekiwanie zmodyfikowana podczas pętli, np. Jeśli nazwa klasy, przez którą zostały wybrane, zostanie usunięta. ;-)
RobG

20

Używasz tablicy jako obiektu, różnica między getElementbyIdi getElementsByClassNamejest taka, że:

  • getElementbyIdzwróci obiekt Element lub wartość null, jeśli nie zostanie znaleziony żaden element o identyfikatorze
  • getElementsByClassNamezwróci aktywny HTMLCollection , prawdopodobnie o długości 0, jeśli nie zostaną znalezione żadne pasujące elementy

getElementsByClassName

getElementsByClassName(classNames)Metoda pobiera ciąg, który zawiera nieuporządkowana zestaw unikatowych tokenów oddzielonych spacjami reprezentujących klas. Po wywołaniu metoda musi zwrócić aktywny NodeListobiekt zawierający wszystkie elementy w dokumencie, które mają wszystkie klasy określone w tym argumencie, po uzyskaniu klas przez podzielenie ciągu na spacje. Jeśli w argumencie nie określono żadnych tokenów, metoda musi zwrócić pustą listę NodeList.

https://www.w3.org/TR/2008/WD-html5-20080610/dom.html#getelementsbyclassname

getElementById

Metoda getElementById () uzyskuje dostęp do pierwszego elementu o określonym identyfikatorze.

https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById

w twoim kodzie linie:

1- document.getElementsByClassName ('myElement'). Style.size = '100px';

NIE będzie działać zgodnie z oczekiwaniami, ponieważ getElementByClassNamezwróci tablicę, a tablica NIE będzie miała stylewłaściwości, do każdej elementz nich można uzyskać dostęp poprzez iterację.

Dlatego funkcja getElementByIddziałała dla Ciebie, ta funkcja zwróci bezpośredni obiekt. Dzięki temu będziesz mógł uzyskać dostęp do stylenieruchomości.


Zwróć uwagę, że specyfikacje whatwg, które są implementowane przez przeglądarki, różnią się od tych w3c tutaj, pierwsza (a więc obecne przeglądarki) zwracają HTMLCollection dla getElementsByClassName, a nie NodeList. Niewielkie, ale może niektórych zmylić.
Kaiido

@ Kaiido - praktyczna różnica polega na…? W moim rozumieniu NodeList to ogólna kolekcja elementów DOM i jest dostępna w każdym DOM, a nie tylko w HTML DOM (np. XML DOM), podczas gdy HTMLCollection jest dla HTML DOM (oczywiście). Jedyną różnicą, jaką widzę, jest metoda namedItem obiektu HTMLCollection .
RobG

Wybór PS Nit: link do standardu WHATWG HTML Living Standard i standardu W3C HTML 5.2 . Zepsuty z wyboru. ;-) Nie ma to jednak znaczenia w kwestii, którą podniosłeś.
RobG

@RobG NodeList ma wiele metod , które nie są dostępne w HTMLCollection.
Kaiido

@ Kaiido-pewny, ale forEach nie jest określony jako część interfejsu dla obu kolekcji lub liście węzłów przez W3C i WHATWG, to określony osobno, na przykład jako własność kolekcji generycznych w Web IDL specyfikacji więc powinny mieć zastosowanie do obu zbiorów i NodeLists (chociaż zgadzam się, że kolekcja zwrócona przez getElementsByClassName nie ma metody forEach ). Myślę, że najważniejsze jest to, że jest wystarczająco dużo historii, aby opowiedzieć ją dobrą odpowiedzią. :-)
RobG

11

Poniższy opis pochodzi z tej strony :

Metoda getElementsByClassName () zwraca kolekcję wszystkich elementów w dokumencie o określonej nazwie klasy jako obiekt NodeList.

Obiekt NodeList reprezentuje kolekcję węzłów. Dostęp do węzłów można uzyskać za pomocą numerów indeksu. Indeks zaczyna się od 0.

Porada: Możesz użyć właściwości length obiektu NodeList do określenia liczby elementów o określonej nazwie klasy, a następnie możesz przejrzeć wszystkie elementy w pętli i wyodrębnić żądane informacje.

Zatem jako parametr getElementsByClassNamezaakceptowałby nazwę klasy.

Jeśli to jest Twoja treść HTML:

<div id="first" class="menuItem"></div>
<div id="second" class="menuItem"></div>
<div id="third" class="menuItem"></div>
<div id="footer"></div>

wtedy var menuItems = document.getElementsByClassName('menuItem')zwróci kolekcję (nie tablicę) 3 górnych <div>s, ponieważ pasują one do podanej nazwy klasy.

Następnie możesz iterować po tej <div>kolekcji węzłów ( w tym przypadku) za pomocą:

for (var menuItemIndex = 0 ; menuItems.length ; menuItemIndex ++) {
   var currentMenuItem = menuItems[menuItemIndex];
   // do stuff with currentMenuItem as a node.
}

Więcej informacji na temat różnic między elementami i węzłami można znaleźć w tym poście .


11

ES6 zapewnia Array.from()metodę, która tworzy nową instancję Array z obiektu przypominającego tablicę lub iterowalnego obiektu.

let boxes = document.getElementsByClassName('box');

Array.from(boxes).forEach(v => v.style.background = 'green');
console.log(Array.from(boxes));
.box {
  width: 50px;
  height: 50px;
  margin: 5px;
  background: blue;
  display: inline-block;
}
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>

Jak widać we fragmencie kodu, po użyciu Array.from()funkcji możesz następnie manipulować każdym elementem.


To samo rozwiązanie przy użyciu jQuery.

$('.box').css({'background':'green'});
.box {
  width: 50px;
  height: 50px;
  margin: 5px;
  background: blue;
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>


7

Innymi słowy

  • document.querySelector()Wybiera tylko pierwszy jednego elementu określonego przełącznika. Więc nie wypluwa tablicy, to pojedyncza wartość. Podobnie jak w przypadku document.getElementById()pobierania tylko elementów identyfikatora, ponieważ identyfikatory muszą być unikalne.

  • document.querySelectorAll()wybiera wszystkie elementy z określonym selektorem i zwraca je w tablicy. Podobnie jak tylko document.getElementsByClassName()dla klas i document.getElementsByTagName()tagów.


Dlaczego warto korzystać z querySelector?

Jest używany wyłącznie w celu ułatwienia i zwięzłości.


Dlaczego warto korzystać z getElement / sBy? *

Szybsza wydajność.


Skąd ta różnica w wydajności?

Oba sposoby wyboru mają na celu utworzenie NodeList do dalszego użytku. querySelectors generuje statyczną listę NodeList z selektorami, dlatego należy ją najpierw utworzyć od podstaw.
getElement / sBy * natychmiast dostosowuje istniejącą na żywo listę NodeList bieżącego DOM.

Kiedy więc użyć której metody, zależy to od Ciebie / Twojego projektu / Twojego urządzenia.


Infos

Demo wszystkich metod Test wydajności
dokumentacji NodeList


4

Zwraca listę podobną do tablicy.

Zrobisz to jako Array jako przykład

var el = getElementsByClassName("elem");
el = Array.prototype.slice.call(el); //this line
el[0].appendChild(otherElem);  

4

Możesz uzyskać pojedynczy element, uruchamiając

document.querySelector('.myElement').style.size = '100px';

ale zadziała dla pierwszego elementu z klasą .myElement.

Jeśli chcesz zastosować to do wszystkich elementów z klasą, proponuję użyć

document.querySelectorAll('.myElement').forEach(function(element) {
    element.style.size = '100px';
});

4
/*
 * To hide all elements with the same class, 
 * use looping to reach each element with that class. 
 * In this case, looping is done recursively
 */

const hideAll = (className, i=0) => {
if(!document.getElementsByClassName(className)[i]){ //exits the loop when element of that id does not exist
  return; 
}

document.getElementsByClassName(className)[i].style.visibility = 'hidden'; //hide element
return hideAll(className, i+1) //loop for the next element
}

hideAll('appBanner') //the function call requires the class name

0

Z ES5 + (dowolne przeglądane obecnie - 2017) powinieneś być w stanie to zrobić

[].forEach.call(document.getElementsByClassName('answer'), function(el) {
    el.style.color= 'red';
});


0

Odpowiedź na konkretny przypadek Drenzii ...

Możesz stworzyć funkcję, która będzie działać dla dowolnego wordelementu i przekazać numer tego, który chcesz przekształcić, na przykład:

// Binds `wordButtons` to an (array-like) HTMLCollection of buttons
const wordButtons = document.getElementsByClassName("word");

// Applies the `slantWord` function to the first word button
slantWord(1);

// Defines the `slantWord` function
function slantWord(wordNumber) {
  const index = wordNumber - 1; // Collection index is zero-based
  wordButtons[index].style.transform = "rotate(7deg)"; // Transforms the specified button
}
<div class="wordGameContainer">
  <button class="word word1">WORD 1</button>
  <button class="word word2">WORD 2</button>
  <button class="word word3">WORD 3</button>
  <button class="word word4">WORD 4</button>
</div>

<div>
  <button onclick="moveWord()" class="playButton">PLAY</button>
</div>

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.