Was geben die Methoden querySelectorAll und getElementsBy * zurück?


151

Do getElementsByClassName(und ähnliche Funktionen wie getElementsByTagNameund querySelectorAll) Arbeit die gleiche wie getElementByIdoder kehren sie eine Reihe von Elementen?

Der Grund, den ich frage, ist, dass ich versuche, den Stil aller Elemente mit zu ändern getElementsByClassName. Siehe unten.

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

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

37
Der Hinweis liegt sehr im Namen: getElementsByClassName()impliziert einen Plural, während getElementById()ein singuläres Elementelement impliziert wird.
David sagt, Monica

1
Ich verstehe, es hat für mich einfach keinen Sinn gemacht, dass Sie nicht alle Elemente mit diesem Klassennamen mit dem obigen Code ändern können, anstatt ein Array durchlaufen zu müssen. jquery way ist viel besser, ich war nur neugierig auf den js way
dmo

Antworten:


152

Ihr getElementById()Code funktioniert, da IDs eindeutig sein müssen und die Funktion daher immer genau ein Element zurückgibt (oder nullwenn keines gefunden wurde).

Jedoch getElementsByClassName(), querySelectorAll()und andere getElementsBy*Methoden ein Array artige Sammlung von Elementen. Iterieren Sie darüber wie bei einem echten Array:

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

Wenn Sie etwas kürzeres bevorzugen, sollten Sie jQuery verwenden :

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

1
Gilt das auch für das, <iframe>was auch Teil Ihrer Domain ist
JMASTER B

3
Es ist 2018 ... Erstellen Sie einfach eine Wrapper-Funktion für querySelectorAll()und Sie können einen schönen Kurzcode ohne eine große Abhängigkeit der alten Schule haben. qSA(".myElement").forEach(el => el.style.size = "100px")Vielleicht soll der Wrapper einen Rückruf erhalten. qSA(".myElement", el => el.style.size = "100px")

2
"Wenn Sie etwas kürzeres bevorzugen, sollten Sie erwägen, Ihrem Projekt eine riesige Bibliothek hinzuzufügen." Ich weiß, 2012 war eine andere Zeit, aber selbst dann hätte ich dieses Stück als lächerlich empfunden.
CoryCoolguy

1
" Iterieren Sie darüber wie mit einem echten Array ... Vorsicht, getElementsByClassName gibt eine Live- NodeList zurück, die während der Schleife unerwartet geändert werden kann, z. B. wenn der Klassenname, von dem sie ausgewählt wurden, entfernt wird. ;-)
RobG

20

Sie verwenden ein Array als Objekt. Der Unterschied zwischen getElementbyIdund getElementsByClassNamebesteht darin, dass:

  • getElementbyIdgibt ein Element-Objekt oder null zurück, wenn kein Element mit der ID gefunden wird
  • getElementsByClassNamegibt eine Live-HTMLCollection zurück , möglicherweise mit der Länge 0, wenn keine übereinstimmenden Elemente gefunden werden

getElementsByClassName

Die getElementsByClassName(classNames)Methode verwendet eine Zeichenfolge, die einen ungeordneten Satz eindeutiger, durch Leerzeichen getrennter Token enthält, die Klassen darstellen. Beim Aufruf muss die Methode ein Live- NodeListObjekt zurückgeben, das alle Elemente im Dokument enthält, die alle in diesem Argument angegebenen Klassen enthalten, nachdem die Klassen durch Aufteilen einer Zeichenfolge auf Leerzeichen erhalten wurden. Wenn im Argument keine Token angegeben sind, muss die Methode eine leere NodeList zurückgeben.

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

getElementById

Die Methode getElementById () greift auf das erste Element mit der angegebenen ID zu.

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

in Ihrem Code die Zeilen:

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

wird nicht wie erwartet funktionieren , weil das getElementByClassNameein Array wird wiederkommen , und das Feld wird NICHT die haben styleEigenschaft können Sie jeden Zugriff elementdurch sie durch Iterieren.

Aus diesem Grund hat die Funktion getElementByIdfür Sie funktioniert. Diese Funktion gibt das direkte Objekt zurück. Daher können Sie auf die Unterkunft zugreifen style.


Beachten Sie, dass sich die von den Browsern implementierten whatwg-Spezifikationen von den w3c-Spezifikationen hier unterscheiden. Die früheren (und damit aktuellen) Browser geben eine HTMLCollection für getElementsByClassName zurück, keine NodeList. Klein, kann aber einige verwirren.
Kaiido

@ Kaiido - der praktische Unterschied ist…? Nach meinem Verständnis ist eine NodeList eine generische Sammlung von DOM-Elementen und in jedem DOM verfügbar, nicht nur in einem HTML-DOM (z. B. einem XML-DOM), während eine HTMLCollection (offensichtlich) für HTML-DOMs vorgesehen ist. Der einzige Unterschied, den ich sehen kann, ist die namedItem- Methode einer HTMLCollection .
RobG

PS Nit pick: Link für den WHATWG HTML Living Standard und den W3C HTML 5.2 Standard . Durch Wahl verwöhnt. ;-) Macht keinen Unterschied zu dem Punkt, den du angesprochen hast.
RobG

@RobG NodeList verfügt über viele Methoden , auf die in HTMLCollection nicht zugegriffen werden kann.
Kaiido

@ Kaiido - sicher, aber forEach wird weder von W3C noch von WHATWG als Teil der Schnittstelle für Sammlung oder NodeList angegeben. Es wird separat angegeben, z. B. als Eigenschaft generischer Sammlungen in der Web-IDL- Spezifikation , sollte also sowohl für Sammlungen als auch für NodeLists gelten (obwohl ich Ihren Standpunkt akzeptiere, dass die von getElementsByClassName zurückgegebene Sammlung keine forEach- Methode hat). Ich denke, das Fazit ist, dass es genug von einer Geschichte gibt, um eine gute Antwort darauf zu geben. :-)
RobG

11

Die folgende Beschreibung stammt von dieser Seite :

Die Methode getElementsByClassName () gibt eine Auflistung aller Elemente im Dokument mit dem angegebenen Klassennamen als NodeList-Objekt zurück.

Das NodeList-Objekt repräsentiert eine Sammlung von Knoten. Auf die Knoten kann über Indexnummern zugegriffen werden. Der Index beginnt bei 0.

Tipp: Sie können die Länge-Eigenschaft des NodeList-Objekts verwenden, um die Anzahl der Elemente mit einem angegebenen Klassennamen zu bestimmen. Anschließend können Sie alle Elemente durchlaufen und die gewünschten Informationen extrahieren.

Als Parameter getElementsByClassNamewürde also ein Klassenname akzeptiert.

Wenn dies Ihr HTML-Text ist:

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

var menuItems = document.getElementsByClassName('menuItem')würde dann eine Sammlung (kein Array) der 3 oberen <div>s zurückgeben, da sie mit dem angegebenen Klassennamen übereinstimmen.

Sie können dann über diese Knotensammlung ( <div>in diesem Fall die Sammlung) iterieren mit:

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

Weitere Informationen zu Unterschieden zwischen Elementen und Knoten finden Sie in diesem Beitrag .


11

ES6 bietet eine Array.from()Methode, mit der eine neue Array-Instanz aus einem Array-ähnlichen oder iterierbaren Objekt erstellt wird.

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>

Wie Sie im Code-Snippet sehen können, können Sie nach Verwendung der Array.from()Funktion jedes Element bearbeiten.


Die gleiche Lösung mit 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

Mit anderen Worten

  • document.querySelector()wählt nur das erste ein Element des angegebenen Selektor. Es wird also kein Array ausgespuckt, sondern ein einzelner Wert. Ähnlich wie beim document.getElementById()Abrufen nur ID-Elemente, da IDs eindeutig sein müssen.

  • document.querySelectorAll()Wählt alle Elemente mit dem angegebenen Selektor aus und gibt sie in einem Array zurück. Ähnlich wie nur document.getElementsByClassName()für Klassen und document.getElementsByTagName()Tags.


Warum querySelector verwenden?

Es wird nur zum Zweck der Leichtigkeit und Kürze verwendet.


Warum getElement / sBy verwenden? *

Schnellere Leistung.


Warum dieser Leistungsunterschied?

Beide Auswahlmöglichkeiten haben den Zweck, eine NodeList zur weiteren Verwendung zu erstellen . querySelectors generiert eine statische NodeList mit den Selektoren, daher muss sie zuerst von Grund auf neu erstellt werden.
getElement / sBy * passt die vorhandene Live-NodeList des aktuellen DOM sofort an.

Wann Sie welche Methode verwenden müssen, liegt bei Ihnen / Ihrem Projekt / Ihrem Gerät.


Infos

Demo aller Methoden
NodeList Dokumentation
Leistungstest


4

Es gibt eine Array-ähnliche Liste zurück.

Sie machen das zu einem Array als Beispiel

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

4

Sie könnten ein einzelnes Element erhalten, indem Sie ausführen

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

Aber es wird für das erste Element mit der Klasse .myElement funktionieren.

Wenn Sie dies für alle Elemente mit der Klasse anwenden möchten, empfehle ich Ihnen, diese zu verwenden

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

Mit ES5 + (heutzutage alle durchsucht - 2017) sollten Sie dazu in der Lage sein

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


0

Eine Antwort auf Drenziis speziellen Fall ...

Sie können eine Funktion erstellen, die für jedes der wordElemente funktioniert, und die Nummer des Elements übergeben, das Sie transformieren möchten, z.

// 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>

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.