QuerySelectorAll ve getElementsBy * yöntemleri ne döndürür?


157

Do getElementsByClassName(ve benzeri benzer işlevler getElementsByTagNameve querySelectorAll) çalışma ile aynı getElementByIdya da elemanlarının bir dizi döndürür mı?

Sormamın nedeni, kullandığım tüm öğelerin stilini değiştirmeye çalışmam getElementsByClassName. Aşağıya bakınız.

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

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

37
İpucu, adda çok fazladır: getElementsByClassName()çoğul getElementById()anlamına gelir , oysa tekil bir öğeyi ifade eder.
David, Monica'nın

1
Anladığım kadarıyla, bir dizide döngü yapmak zorunda kalmadan yukarıdaki kodu kullanarak bu sınıf adına sahip tüm öğeleri değiştiremeyeceğiniz bana mantıklı gelmedi. jquery yolu çok daha iyi, sadece js yolunu merak ediyordum
dmo

1
Ayrıca faydalı olabilir: stackoverflow.com/questions/3871547/…
kapa

Yanıtlar:


155

Kişisel getElementById()kimlikleri benzersiz olmak zorunda ve böylece işlev daima tam olarak bir öğeyi döndürür (ya beri kod çalışır nullhiçbiri bulunmuştur ise).

Bununla birlikte, getElementsByClassName(), querySelectorAll()ve diğer getElementsBy*yöntemler, unsurların bir dizi benzeri toplama döndürür. Gerçek bir dizide yaptığınız gibi üzerinde yineleyin:

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

Daha kısa bir şey tercih ediyorsanız, jQuery kullanmayı düşünün :

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

1
Bu aynı <iframe>zamanda alanınızın bir parçası olan için de geçerli mi
JMASTER B

3
Yıl 2018 ... Sadece için bir sarmalayıcı işlevi oluşturun querySelectorAll()ve büyük, eski usul bir bağımlılık olmadan güzel kısa koda sahip olabilirsiniz. qSA(".myElement").forEach(el => el.style.size = "100px")Belki paketleyicinin bir geri arama almasını sağlayın. qSA(".myElement", el => el.style.size = "100px")

2
"Daha kısa bir şey tercih ederseniz, projenize büyük bir kitaplık eklemeyi düşünün" 2012'nin farklı bir zaman olduğunu biliyorum, ancak o zaman bile bu kısmı gülünç bulabilirdim.
CoryCoolguy

1
" Gerçek bir dizide yaptığınız gibi üzerinde yineleyin… Dikkatli olun, getElementsByClassName döngü sırasında beklenmedik şekilde değiştirilebilecek canlı bir NodeList döndürür , örneğin seçildikleri sınıf adı kaldırılırsa. ;-)
RobG

20

Bir nesne gibi bir dizi kullanırken, arasındaki fark getElementbyIdve getElementsByClassNameolmasıdır:

  • getElementbyIdkimliğine sahip bir öğe bulunmazsa bir Öğe nesnesi veya boş döndürür
  • getElementsByClassNameeşleşen öğe bulunamazsa, muhtemelen uzunluğu 0 olan canlı bir HTMLCollection döndürür

getElementsByClassName

getElementsByClassName(classNames)Yöntem sınıfları temsil eden bir tek alan ayrılmış jeton sırasız grubu içeren bir dizisini alır. Çağrıldığında, yöntem NodeList, bir dizeyi boşluklara bölerek sınıfları elde ederek, o bağımsız değişkende belirtilen tüm sınıflara sahip belgedeki tüm öğeleri içeren canlı bir nesne döndürmelidir . Bağımsız değişkende belirtilmiş simge yoksa, yöntemin boş bir NodeList döndürmesi gerekir.

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

getElementById

GetElementById () yöntemi, belirtilen kimliğe sahip ilk öğeye erişir.

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

kodunuzda satırlar:

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

olacak DEĞİL , çünkü beklendiği gibi çalışma getElementByClassNamebir dizi döndürür ve dizi olacak DEĞİL sahip stylemülkü, her erişebilir elementiçlerinden iterating tarafından.

Bu yüzden işlev getElementByIdsizin için çalıştı, bu işlev doğrudan nesneyi döndürecektir. Bu nedenle, stylemülke erişebileceksiniz .


Tarayıcılar tarafından uygulanan whatwg özelliklerinin buradaki w3c özelliklerinden farklı olduğuna dikkat edin , eski (ve dolayısıyla mevcut tarayıcılar) bir NodeList değil, getElementsByClassName için bir HTMLCollection döndürür. Küçük, ancak bazılarını karıştırabilir.
Kaiido

@ Kaiido - pratik fark…? Anladığım kadarıyla, bir NodeList , DOM öğelerinin genel bir koleksiyonudur ve herhangi bir DOM'da mevcuttur, sadece bir HTML DOM'da (örneğin bir XML DOM) mevcutken, HTMLCollection HTML DOM'lar içindir (tabii ki). Görebilirsiniz tek fark namedItem bir yöntem HTMLCollection .
RobG

PS Nit seçim: WHATWG HTML Living Standard ve W3C HTML 5.2 standardı için bağlantı . Seçimle şımarık. ;-) Yine de dile getirdiğiniz noktada hiçbir fark yaratmaz.
RobG

@RobG NodeList, HTMLCollection'da erişilemeyen birçok yönteme sahiptir.
Kaiido

@ Kaiido - elbette, ancak forEach , toplama veya NodeList by W3C veya WHATWG arabiriminin bir parçası olarak belirtilmemiştir, örneğin Web IDL belirtiminde jenerik koleksiyonların bir özelliği olarak ayrı olarak belirtilmiştir, dolayısıyla hem koleksiyonlar hem de NodeLists için geçerli olmalıdır ( getElementsByClassName tarafından döndürülen koleksiyonun bir forEach yöntemine sahip olmadığını kabul etmeme rağmen ). Sanırım önemli olan, iyi bir cevabın anlatılması için yeterince hikaye olması. :-)
RobG

11

Aşağıdaki açıklama bu sayfadan alınmıştır :

GetElementsByClassName () yöntemi, bir NodeList nesnesi olarak, belirtilen sınıf adına sahip belgedeki tüm öğelerin bir koleksiyonunu döndürür.

NodeList nesnesi bir düğüm koleksiyonunu temsil eder. Düğümlere dizin numaraları ile erişilebilir. Dizin 0'dan başlar.

İpucu: Belirli bir sınıf adına sahip öğelerin sayısını belirlemek için NodeList nesnesinin length özelliğini kullanabilir, ardından tüm öğeler arasında döngü oluşturabilir ve istediğiniz bilgileri çıkarabilirsiniz.

Dolayısıyla, bir parametre olarak getElementsByClassNamebir sınıf adı kabul eder.

Bu sizin HTML gövdenizse:

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

daha sonra , verilen sınıf adıyla eşleştikleri için var menuItems = document.getElementsByClassName('menuItem')üstteki 3 <div>s'nin bir koleksiyonunu (bir dizi değil) döndürür .

Daha sonra bu düğüm ( <div>ler) koleksiyonunu aşağıdakilerle yineleyebilirsiniz :

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

Öğeler ve düğümler arasındaki farklar hakkında daha fazla bilgi için lütfen bu gönderiye bakın .


döngü yanlış görünüyor, for (var menuItemIndex = 0 ; menuItemIndex < menuItems.length ; menuItemIndex ++) {bence olmalı .
David

11

ES6 , Array.from()dizi benzeri veya yinelenebilir bir nesneden yeni bir Dizi örneği oluşturan yöntem sağlar .

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>

Kod parçacığının içinde görebileceğiniz gibi, Array.from()işlevi kullandıktan sonra her bir öğeyi değiştirebilirsiniz.


Aynı çözümü kullanarak 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

Diğer bir deyişle

  • document.querySelector()seçer sadece ilk bir belirtilen seçici elemanı. Yani bir dizi ortaya çıkarmaz, tek bir değerdir. document.getElementById()Kimliklerin benzersiz olması gerektiğinden, yalnızca kimlik öğelerini getirenlere benzer .

  • document.querySelectorAll()belirtilen seçiciye sahip tüm öğeleri seçer ve bunları bir dizide döndürür. Yalnızca document.getElementsByClassName()sınıflar ve document.getElementsByTagName()etiketlere benzer .


Neden querySelector kullanmalı?

Yalnızca kolaylık ve kısalık amacıyla kullanılır.


Neden getElement / sBy kullanıyorsunuz? *

Daha hızlı performans.


Neden bu performans farkı?

Her iki seçim yolu da daha fazla kullanım için bir NodeList oluşturma amacına sahiptir . querySelectors , seçicilerle statik bir NodeList oluşturur, bu nedenle ilk olarak sıfırdan oluşturulması gerekir.
getElement / sBy * , geçerli DOM'un mevcut canlı NodeList'ini anında uyarlar.

Öyleyse, hangi yöntemi ne zaman kullanacağınız size / projenize / cihazınıza bağlıdır.


Bilgi

Tüm yöntemlerin
demosu NodeList Dokümantasyon
Performans Testi


4

Dizi benzeri bir liste döndürür.

Bunu örnek olarak bir Dizi yapıyorsun

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

4

Çalıştırarak tek bir öğe elde edebilirsiniz

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

ancak .myElement sınıfına sahip ilk öğe için çalışacak.

Bunu sınıfın tüm unsurları için uygulamak isterseniz kullanmanızı öneririm.

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

ES5 + ile (bugünlerde herhangi bir göz atılan - 2017) şunları yapabilmelisiniz:

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


0

Drenzii'nin özel durumuna bir cevap ...

Öğelerin herhangi biri için çalışacakword ve dönüştürmek istediğinizin numarasını iletecek bir işlev yapabilirsiniz , örneğin:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.