Cosa restituiscono i metodi querySelectorAll e getElementsBy *?


151

Do getElementsByClassName(e funzioni simili come getElementsByTagNamee querySelectorAll) opera la stessa getElementByIdo se invece restituiscono un array di elementi?

Il motivo per cui lo chiedo è perché sto cercando di cambiare lo stile di tutti gli elementi usando getElementsByClassName. Vedi sotto.

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

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

37
L'indizio è, molto, nel nome: getElementsByClassName()implica un plurale, mentre getElementById()implica un elemento elemento singolare.
David dice di ripristinare Monica

1
Capisco, non aveva senso per me che non puoi cambiare tutti gli elementi con quel nome di classe usando il codice sopra invece di dover passare in rassegna un array. jquery way è molto meglio, ero solo curioso del modo js
dmo

1
Potrebbe anche essere utile: stackoverflow.com/questions/3871547/…
kapa

Risposte:


152

Il getElementById()codice funziona poiché gli ID devono essere univoci e quindi la funzione restituisce sempre esattamente un elemento (o nullse non ne è stato trovato nessuno).

Tuttavia, getElementsByClassName(), querySelectorAll(), e altri getElementsBy*metodi restituiscono una collezione serie simile di elementi. Passa su di esso come faresti con un array reale:

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

Se preferisci qualcosa di più corto, considera l'utilizzo di jQuery :

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

1
Questo vale anche per il <iframe>quale fa parte anche del tuo dominio
JMASTER B

3
È il 2018 ... Basta creare una funzione wrapper per querySelectorAll()e puoi avere un bel codice breve senza una grande dipendenza della vecchia scuola. qSA(".myElement").forEach(el => el.style.size = "100px")Forse il wrapper riceve un callback. qSA(".myElement", el => el.style.size = "100px")

2
"Se preferisci qualcosa di più corto, considera l'aggiunta di un'enorme libreria al tuo progetto" So che il 2012 è stato un periodo diverso, ma anche allora avrei trovato quel po 'ridicolo.
CoryCoolguy

1
" Scorrere su di esso come si farebbe con un vero e proprio allineamento ... Attento, getElementsByClassName restituisce un vivo NodeList che potrebbe essere modificata in modo imprevisto durante il ciclo, ad esempio, se il nome di classe che sono stati selezionati dal viene rimosso ;-).
RobG

20

Stai usando un array come oggetto, la differenza tra getElementbyIded getElementsByClassNameè che:

  • getElementbyIdrestituirà un oggetto Element o null se non viene trovato alcun elemento con l'ID
  • getElementsByClassNamerestituirà una raccolta HTMLC live , possibilmente di lunghezza 0 se non viene trovato alcun elemento corrispondente

getElementsByClassName

Il getElementsByClassName(classNames)metodo accetta una stringa che contiene un set non ordinato di token univoci separati da spazio che rappresentano le classi. Quando viene chiamato, il metodo deve restituire un NodeListoggetto live contenente tutti gli elementi nel documento che hanno tutte le classi specificate in quell'argomento, avendo ottenuto le classi suddividendo una stringa su spazi. Se non sono stati specificati token nell'argomento, il metodo deve restituire un NodeList vuoto.

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

getElementById

Il metodo getElementById () accede al primo elemento con l'id specificato.

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

nel tuo codice le righe:

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

sarà NON funzionano come previsto, perché il getElementByClassNamerestituirà un array, e l'array non hanno la styleproprietà, è possibile accedere ad ogni elementscorrendo attraverso di loro.

Ecco perché la funzione ha getElementByIdfunzionato per te, questa funzione restituirà l'oggetto diretto. Pertanto sarai in grado di accedere alla styleproprietà.


Si noti che le specifiche whatwg implementate dai browser differiscono da quelle del w3c qui, le prime (e quindi i browser attuali) restituiscono un HTMLCollection per getElementsByClassName, non un NodeList. Minore, ma può confondere alcuni.
Kaiido,

@ Kaiido: la differenza pratica è ...? A mio avviso , un NodeList è una raccolta generica di elementi DOM ed è disponibile in qualsiasi DOM, non solo un DOM HTML (ad esempio un DOM XML), mentre un HTMLCollection è per DOM HTML (ovviamente). L'unica differenza che posso vedere è il metodo denominatoItem di un HTMLCollection .
RobG

Scelta PS Nit: link per WHATWG HTML Living Standard e W3C HTML 5.2 standard . L'imbarazzo della scelta. ;-) Tuttavia, non fa alcuna differenza sul punto sollevato.
RobG

@RobG NodeList ha molti metodi che non sono accessibili su HTMLCollection.
Kaiido,

@ Kaiido: certo, ma forEach non è specificato come parte dell'interfaccia per collection o NodeList da W3C o WHATWG, è specificato separatamente, ad es. Come una proprietà di raccolte generiche nella specifica IDL Web, quindi dovrebbe applicarsi sia alle raccolte che alle NodeList (anche se accetto il punto che la raccolta restituita da getElementsByClassName non ha un metodo forEach ). Immagino che la linea di fondo sia che c'è abbastanza storia per una buona risposta da raccontare. :-)
RobG

11

La seguente descrizione è tratta da questa pagina :

Il metodo getElementsByClassName () restituisce una raccolta di tutti gli elementi nel documento con il nome classe specificato, come oggetto NodeList.

L'oggetto NodeList rappresenta una raccolta di nodi. È possibile accedere ai nodi tramite numeri di indice. L'indice inizia da 0.

Suggerimento: è possibile utilizzare la proprietà length dell'oggetto NodeList per determinare il numero di elementi con un nome di classe specificato, quindi è possibile scorrere tutti gli elementi ed estrarre le informazioni desiderate.

Quindi, come parametro getElementsByClassNameaccetterebbe un nome di classe.

Se questo è il tuo corpo HTML:

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

quindi var menuItems = document.getElementsByClassName('menuItem')restituirebbe una raccolta (non un array) delle 3 <div>s superiori , poiché corrispondono al nome della classe specificato.

Puoi quindi scorrere su questa <div>raccolta di nodi ( s in questo caso) con:

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

Si prega di fare riferimento a questo post per ulteriori informazioni sulle differenze tra elementi e nodi.


il ciclo sembra sbagliato, dovrebbe essere for (var menuItemIndex = 0 ; menuItemIndex < menuItems.length ; menuItemIndex ++) {secondo me.
David

11

ES6 fornisce il Array.from()metodo, che crea una nuova istanza di array da un oggetto simile a array o iterabile.

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>

Come puoi vedere all'interno dello snippet di codice, dopo aver utilizzato la Array.from()funzione sei in grado di manipolare ogni elemento.


La stessa soluzione usando 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

In altre parole

  • document.querySelector()seleziona solo il primo un elemento del selettore specificato. Quindi non sputa fuori un array, è un singolo valore. Simile al document.getElementById()quale recupera solo gli elementi ID, poiché gli ID devono essere univoci.

  • document.querySelectorAll()seleziona tutti gli elementi con il selettore specificato e li restituisce in un array. Simile a solo document.getElementsByClassName()per classi e document.getElementsByTagName()tag.


Perché usare querySelector?

È usato solo per il solo scopo di facilità e brevità.


Perché usare getElement / sBy? *

Prestazioni più veloci.


Perché questa differenza di prestazioni?

Entrambe le modalità di selezione hanno lo scopo di creare una NodeList per un ulteriore utilizzo. querySelectors genera una NodeList statica con i selettori, quindi deve essere prima creata da zero.
getElement / sBy * adatta immediatamente la NodeList live esistente del DOM corrente.

Quindi, quando usare quale metodo dipende da te / dal tuo progetto / dal tuo dispositivo.


informazioni

Demo di tutti i metodi Test delle prestazioni della
documentazione di NodeList


4

Restituisce un elenco simile a una matrice.

Lo fai come un array

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

4

È possibile ottenere un singolo elemento eseguendo

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

ma funzionerà per il primo elemento con classe .myElement.

Se desideri applicare questo per tutti gli elementi con la classe ti suggerisco di usare

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

Con ES5 + (qualsiasi navigato al giorno d'oggi - 2017) dovresti essere in grado di farlo

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


0

Una risposta per il caso specifico di Drenzii ...

Potresti creare una funzione che funzionerà per uno qualsiasi degli wordelementi e passare il numero di quello che vuoi trasformare, come:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.