Apa yang dikembalikan metode querySelectorAll dan getElementsBy *?


151

Apakah getElementsByClassName(dan fungsi serupa suka getElementsByTagNamedan querySelectorAll) bekerja sama getElementByIdatau apakah mereka mengembalikan array elemen?

Alasan saya bertanya adalah karena saya mencoba mengubah gaya semua elemen menggunakan getElementsByClassName. Lihat di bawah.

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

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

37
Petunjuknya adalah, sangat banyak, dalam nama: getElementsByClassName()menyiratkan jamak, sedangkan getElementById()menyiratkan item elemen tunggal.
David mengatakan mengembalikan Monica

1
Saya mengerti, itu tidak masuk akal bagi saya bahwa Anda tidak dapat mengubah semua elemen dengan nama kelas menggunakan kode di atas daripada harus melalui array. cara jquery jauh lebih baik, saya hanya ingin tahu tentang cara js
dmo

1
Mungkin bermanfaat juga: stackoverflow.com/questions/3871547/…
kapa

Jawaban:


152

getElementById()Kode Anda berfungsi karena ID harus unik dan karenanya fungsi selalu mengembalikan tepat satu elemen (atau nulljika tidak ada yang ditemukan).

Namun, getElementsByClassName(), querySelectorAll(), dan lainnya getElementsBy*metode mengembalikan koleksi array seperti elemen. Iterate seperti itu dengan array nyata:

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

Jika Anda lebih suka sesuatu yang lebih pendek, pertimbangkan untuk menggunakan jQuery :

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

1
Apakah itu juga berlaku untuk <iframe>yang juga merupakan bagian dari domain Anda
JMASTER B

3
Ini tahun 2018 ... Cukup buat fungsi wrapper untuk querySelectorAll()dan Anda dapat memiliki kode pendek yang bagus tanpa ketergantungan sekolah lama yang besar. qSA(".myElement").forEach(el => el.style.size = "100px")Mungkin pembungkus menerima panggilan balik. qSA(".myElement", el => el.style.size = "100px")

2
"Jika Anda lebih suka sesuatu yang lebih pendek, pertimbangkan untuk menambahkan perpustakaan besar ke proyek Anda" Saya tahu 2012 adalah waktu yang berbeda, tetapi bahkan kemudian saya akan menemukan sedikit menggelikan.
CoryCoolguy

1
" Iterasi seperti yang Anda lakukan dengan array nyata ... Hati-hati, getElementsByClassName mengembalikan NodeList langsung yang mungkin dimodifikasi secara tak terduga selama loop, misalnya jika nama kelas yang dipilih akan dihapus. ;-)
RobG

20

Anda menggunakan array sebagai objek, perbedaan antara getElementbyIddan getElementsByClassNameadalah:

  • getElementbyIdakan mengembalikan objek Elemen atau null jika tidak ada elemen dengan ID yang ditemukan
  • getElementsByClassNameakan mengembalikan HTMLCollection langsung , mungkin dengan panjang 0 jika tidak ada elemen yang cocok ditemukan

getElementsByClassName

The getElementsByClassName(classNames)Metode mengambil string yang berisi unordered set token ruang yang dipisahkan unik yang mewakili kelas. Ketika dipanggil, metode harus mengembalikan NodeListobjek hidup yang berisi semua elemen dalam dokumen yang memiliki semua kelas yang ditentukan dalam argumen itu, setelah memperoleh kelas dengan memisahkan string pada spasi. Jika tidak ada token yang ditentukan dalam argumen, maka metode harus mengembalikan NodeList kosong.

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

getElementById

Metode getElementById () mengakses elemen pertama dengan id yang ditentukan.

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

dalam kode Anda, baris:

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

TIDAK akan bekerja seperti yang diharapkan, karena getElementByClassNameakan mengembalikan array, dan array TIDAK akan memilikistyle properti, Anda dapat mengaksesnyaelement dengan mengulangi melalui mereka.

Itu sebabnya fungsi getElementByIdbekerja untuk Anda, fungsi ini akan mengembalikan objek langsung. Karena itu Anda akan dapat mengakses styleproperti.


Perhatikan bahwa spesifikasi whatwg yang sedang diterapkan oleh browser memang berbeda dari yang w3c di sini, yang sebelumnya (dan karenanya browser saat ini) mengembalikan HTMLCollection untuk getElementsByClassName, bukan NodeList. Kecil, tetapi mungkin membingungkan beberapa.
Kaiido

@ Kaiido — perbedaan praktisnya adalah ...? Menurut pemahaman saya, NodeList adalah kumpulan generik elemen DOM dan tersedia di DOM apa pun, bukan hanya HTML DOM (misalnya XML DOM), sedangkan HTMLCollection adalah untuk HTML DOMs (jelas). Satu-satunya perbedaan yang dapat saya lihat adalah metode nameItem dari HTMLCollection .
RobG

PS Nit pick: tautan untuk WHATWG HTML Living Standard dan W3C HTML 5.2 standar . Dimanjakan oleh pilihan. ;-) Tidak ada bedanya dengan poin yang Anda angkat.
RobG

@RobG NodeList memiliki banyak metode yang tidak dapat diakses di HTMLCollection.
Kaiido

@ Kaiido — tentu saja, tetapi forEach tidak ditentukan sebagai bagian dari antarmuka untuk koleksi atau NodeList oleh W3C atau WHATWG, itu ditentukan secara terpisah, misalnya sebagai properti koleksi generik dalam spesifikasi Web IDL jadi harus berlaku untuk koleksi dan NodeLists (meskipun saya menerima pendapat Anda bahwa koleksi dikembalikan oleh getElementsByClassName tidak memiliki metode forEach ). Saya kira intinya adalah bahwa ada cukup cerita untuk jawaban yang baik untuk menceritakannya. :-)
RobG

11

Deskripsi berikut diambil dari halaman ini :

Metode getElementsByClassName () mengembalikan koleksi semua elemen dalam dokumen dengan nama kelas yang ditentukan, sebagai objek NodeList.

Objek NodeList mewakili kumpulan node. Node dapat diakses dengan nomor indeks. Indeks dimulai pada 0.

Tip: Anda bisa menggunakan properti panjang objek NodeList untuk menentukan jumlah elemen dengan nama kelas yang ditentukan, lalu Anda bisa mengulang semua elemen dan mengekstrak info yang Anda inginkan.

Jadi, sebagai parameter getElementsByClassName akan menerima nama kelas.

Jika ini adalah badan HTML Anda:

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

maka var menuItems = document.getElementsByClassName('menuItem')akan mengembalikan koleksi (bukan array) dari 3 atas<div> , karena cocok dengan nama kelas yang diberikan.

Anda kemudian dapat mengulangi <div>koleksi node ini ( dalam hal ini) dengan:

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

Silakan merujuk ke posting ini untuk lebih lanjut tentang perbedaan antara elemen dan node.


loop terlihat salah, harus for (var menuItemIndex = 0 ; menuItemIndex < menuItems.length ; menuItemIndex ++) {menurut saya.
David

11

ES6 menyediakan Array.from()metode, yang membuat instance Array baru dari objek mirip-array atau yang dapat diulang.

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>

Seperti yang Anda lihat di dalam cuplikan kode, setelah menggunakan Array.from() fungsi Anda kemudian dapat memanipulasi setiap elemen.


Solusi yang sama menggunakan 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

Dengan kata lain

  • document.querySelector()menyeleksi hanya yang pertama salah satu elemen dari pemilih yang ditentukan. Jadi itu tidak memunculkan array, itu adalah nilai tunggal. Mirip dengan document.getElementById()yang mengambil elemen ID saja, karena ID harus unik.

  • document.querySelectorAll()memilih semua elemen dengan pemilih yang ditentukan dan mengembalikannya dalam array. Mirip dengan document.getElementsByClassName()untuk kelas dan document.getElementsByTagName()tag saja.


Mengapa menggunakan querySelector?

Ini digunakan hanya untuk tujuan kemudahan dan keringkasan saja.


Mengapa menggunakan getElement / sBy? *

Performa lebih cepat.


Mengapa perbedaan kinerja ini?

Kedua cara pemilihan memiliki tujuan untuk menciptakan NodeList untuk digunakan lebih lanjut. querySelectors menghasilkan NodeList statis dengan pemilih sehingga harus dibuat terlebih dahulu dari awal.
getElement / sBy * segera menyesuaikan NodeList langsung yang ada dari DOM saat ini.

Jadi, kapan harus menggunakan metode mana terserah Anda / proyek Anda / perangkat Anda.


informasi

Demo semua metode Tes Kinerja
Dokumentasi NodeList


4

Ini mengembalikan daftar seperti array.

Anda menjadikan Array sebagai contoh

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

4

Anda bisa mendapatkan elemen tunggal dengan menjalankan

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

tapi itu akan bekerja untuk elemen pertama dengan class .myElement.

Jika Anda ingin menerapkan ini untuk semua elemen dengan kelas saya sarankan Anda untuk menggunakannya

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

Dengan ES5 + (semua yang diramban saat ini - 2017) Anda harus dapat melakukannya

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


0

Sebuah jawaban untuk kasus spesifik Drenzii ...

Anda bisa membuat fungsi yang akan berfungsi untuk salah satu wordelemen dan memasukkan jumlah yang ingin Anda ubah, seperti:

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.