javascript - Vad returnerar metoderna querySelectorAll() och getElementsBy*()?
Fungerar getElementsByClassName (och liknande funktioner som getElementsByTagName och querySelectorAll) som getElementById eller returnerar de en array av element?
Anledningen till att jag frågar är eftersom jag försöker ändra stilen på alla element med getElementsByClassName. Se nedan.
//doesn't work
document.getElementsByClassName('myElement').style.size = '100px';
//works
document.getElementById('myIdElement').style.size = '100px';
Svar #1
Din getElementById-kod fungerar eftersom ID:n måste vara unika och därför returnerar funktionen alltid exakt ett element (eller null om inget hittades).
Men metoderna getElementsByClassName, getElementsByName, getElementsByTagName och getElementsByTagNameNS returnerar en itererbar samling av element.
Metodnamnen ger ledtråden: getElement antyder singular, medan getElements antyder plural.
Metoden querySelector returnerar också ett enskilt element, och querySelectorAll returnerar en itererbar samling.
Den itererbara samlingen kan antingen vara en NodeList eller en HTMLCollection.
getElementsByName och querySelectorAll är båda specificerade att returnera en NodeList; de andra getElementsBy*-metoderna är specificerade att returnera en HTMLCollection, men observera att vissa webbläsarversioner implementerar detta annorlunda.
Båda dessa samlingstyper erbjuder inte samma egenskaper som Element, Noder eller liknande typer erbjuder; det är därför man läser Style från document.getElements... (... ) misslyckas. Med andra ord: en NodeList eller en HTMLCollection har ingen stil; endast ett Element har en stil.
Dessa "array-liknande" samlingar är listor som innehåller noll eller fler element, som du behöver iterera över för att komma åt dem. Även om du kan iterera över dem på ett liknande sätt som en array, notera att de är olika från Array.
I moderna webbläsare kan du konvertera dessa iterables till en riktig Array med Array.from; sedan kan du använda forEach och andra Array-metoder, t.ex. itereringsmetoder:
Array.from(document.getElementsByClassName("myElement"))
.forEach((element) => element.style.size = "100px");
I gamla webbläsare som inte stöder Array.from eller itereringsmetoderna kan du fortfarande använda Array.prototype.slice.call. Sedan kan du iterera över det som du skulle göra med en riktig array:
var elements = Array.prototype.slice
.call(document.getElementsByClassName("myElement"));
for(var i = 0; i < elements.length; ++i){
elements[i].style.size = "100px";
}
Du kan också iterera över NodeList eller HTMLCollection direkt, men var medveten om att dessa samlingar under de flesta omständigheter är levande (MDN-dokumentation, DOM-specifikation), dvs. de uppdateras när DOM ändras. Så om du infogar eller tar bort element medan du loopar, se till att inte av misstag hoppa över några element eller skapa en oändlig loop. MDN-dokumentation bör alltid ange om en metod returnerar en levande samling eller en statisk.
Till exempel erbjuder en NodeList vissa itereringsmetoder såsom forEach i moderna webbläsare:
document.querySelectorAll(".myElement")
.forEach((element) => element.style.size = "100px");
En enkel for-loop kan också användas:
var elements = document.getElementsByClassName("myElement");
for(var i = 0; i < elements.length; ++i){
elements[i].style.size = "100px";
}
Sidnot: .childNodes ger en levande NodeList och .children ger en levande HTMLCollection, så dessa två getters behöver också hanteras försiktigt.
Det finns vissa bibliotek som jQuery som gör DOM-förfrågningar lite kortare och skapar ett abstraktionslager över "ett element" och "en samling element".
$(".myElement").css("size", "100px");
Svar #2
Du använder en array som ett objekt, skillnaden mellan getElementbyId och getElementsByClassName är att:
getElementbyIdkommer att returnera ett Element-objekt eller null om inget element med ID:t hittasgetElementsByClassNamekommer att returnera en levande HTMLCollection, möjligen med längd 0 om inga matchande element hittas
getElementsByClassName
Metoden
getElementsByClassName(classNames)tar en sträng som innehåller en oordnad uppsättning unika mellanslagsseparerade token som representerar klasser. När den anropas måste metoden returnera ett aktivtNodeList-objekt som innehåller alla element i dokumentet som har alla klasser som anges i det argumentet, efter att ha fått klasserna genom att dela upp en sträng vid mellanslag. Om inga token anges i argumentet, måste metoden returnera en tom NodeList.
https://www.w3.org/TR/2008/WD-html5-20080610/dom.html#getelementsbyclassname
getElementById
Metoden getElementById() får åtkomst till det första elementet med det angivna id:t.
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById
i din kod raderna:
1- document.getElementsByClassName('myElement').style.size='100px';
kommer INTE att fungera som förväntat, eftersom getElementByClassName kommer att returnera en array, och arrayen kommer INTE att ha egenskapen style. Du kan komma åt varje element genom att iterera genom dem.
Det är därför funktionen getElementById fungerade för dig, denna funktion kommer att returnera objektet direkt. Därför kommer du att kunna komma åt style-egenskapen.
Svar #3
ES6 tillhandahåller Array.from()-metoden, som skapar en ny Array-instans från ett array-liknande eller itererbart objekt.
let boxes = document.getElementsByClassName('box');
setTimeout(() => {
Array.from(boxes).forEach(v => v.style.background = 'green');
console.log(Array.from(boxes));
}, 500);.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>Som du kan se i kodsnutten, efter att ha använt Array.from()-funktionen kan du sedan manipulera varje element.
$('.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>Svar #4
Följande beskrivning är hämtad från denna sida:
Metoden getElementsByClassName() returnerar en samling av alla element i dokumentet med det angivna klassnamnet, som ett NodeList-objekt.
NodeList-objektet representerar en samling av noder. Noderna kan nås via indexnummer. Indexet börjar på 0.
Tips: Du kan använda length-egenskapen hos NodeList-objektet för att bestämma antalet element med ett angivet klassnamn, sedan kan du loopa igenom alla element och extrahera den information du vill ha.
Så, som en parameter skulle getElementsByClassName acceptera ett klassnamn.
Om detta är din HTML-kropp:
<div id="first" class="menuItem"></div>
<div id="second" class="menuItem"></div>
<div id="third" class="menuItem"></div>
<div id="footer"></div>
då skulle var menuItems=document.getElementsByClassName('menuItem') returnera en samling (inte en array) av de 3 översta <div>-elementen, eftersom de matchar det angivna klassnamnet.
Du kan sedan iterera över denna nodsamling (<div>-element i detta fall) med:
for (var menuItemIndex = 0 ; menuItemIndex < menuItems.length ; menuItemIndex ++) {
var currentMenuItem = menuItems[menuItemIndex];
// do stuff with currentMenuItem as a node.
}
Vänligen hänvisa till detta inlägg för mer om skillnader mellan element och noder.
