GetElementsByClassName aracılığıyla doğru şekilde yineleme nasıl yapılır


108

Ben Javascript acemisiyim.

Web sayfasını aracılığıyla başlatıyorum window.onload, sınıf adlarına ( slide) göre bir dizi öğeyi bulmam ve bunları bir mantığa göre farklı düğümlere yeniden dağıtmam gerekiyor. Distribute(element)Girdi olarak bir eleman alan ve dağıtımı yapan bir işleve sahibim . Bunun gibi bir şey yapmak istiyorum (örneğin burada veya burada ana hatlarıyla belirtildiği gibi ):

var slides = getElementsByClassName("slide");
for(var i = 0; i < slides.length; i++)
{
   Distribute(slides[i]);
}

ancak bu benim için sihir yapmıyor, çünkü getElementsByClassNameaslında dizi döndürmüyor, ama a NodeList, yani ...

... bu benim spekülasyonum ...

... işlev içinde değiştiriliyor Distribute(DOM ağacı bu işlev içinde değiştiriliyor ve belirli düğümlerin klonlanması gerçekleşiyor). For-eachdöngü yapısı da yardımcı olmuyor.

Değişken slaytlar, her yinelemede, uzunluğunu ve öğelerin sırasını çılgınca değiştirdiği için gerçekten belirsizdir.

Benim durumumda NodeList aracılığıyla yinelemenin doğru yolu nedir? Bazı geçici dizileri doldurmayı düşünüyordum ama bunu nasıl yapacağımdan emin değilim ...

DÜZENLE:

Bahsetmeyi unuttuğum önemli bir gerçek, diğerinin içinde bir slayt olabileceğidir, bu aslında slidesdeğişkeni değiştiren şey, Alohci kullanıcısı sayesinde yeni öğrendiğim gibi .

Benim için çözüm, her öğeyi önce bir diziye klonlamak ve diziyi tek tek Distribute()daha sonra geçirmekti .


3
Aslında bunu yapmanın yolu bu, bu yüzden başka bir şeyi alt üst ediyor olmalısın!
adeneo

Distribute()fonksiyon uzun ve karmaşık burada kopyalanacak olan, ama ben DOM yapısı içini değişen am eminim, ben de çoğaltarak ediyorum unsurlar var (klonlama). Hata ayıkladığımda, değişken slidesher geçişte değiştiğini görebiliyorum .
Kupto

Siz gerçekten bir yerde değiştirmedikçe değişmez.
adeneo

5
Bunun getElementsByClassName()canlı nodeListolarak döndüğüne inanıyorum , böylece o sınıftaki öğeler, nodeListüzerinde yinelediğiniz değişikliklerin uzunluğuna eklenir .
David, Monica

2
@ Kupto-tersine döngüleme genellikle bu tür bir sorunu çözer; Dağıt işlevi, David Thomas'ın verdiği nedenden ötürü, öğeyi artık getElementsByClassName çağrısıyla eşleşmeyecek şekilde kaldırır veya taşır.
Alohci

Yanıtlar:


136

MDN'ye göre, bir öğeyi a'dan almanın yolu NodeList:

nodeItem = nodeList.item(index)

Böylece:

var slides = document.getElementsByClassName("slide");
for (var i = 0; i < slides.length; i++) {
   Distribute(slides.item(i));
}

Bunu kendim denemedim (normal fordöngü benim için her zaman çalıştı), ama bir şans ver.


Aynı sınıfa sahip ve birbirinin içinde olan öğeleri aramaya ve değiştirmeye çalışmadığınız sürece bu doğru çözümdür. Soruyu düzenlerken geçici çözümümü açıkladım.
Kupto

Tabii, bunu hesaba katmadım.
Albert Xing

Sorabilirsem neden bu şekilde? Bunun gibi düğümler üzerinde yineleme yapabilmeniz için neden uygulanmıyor for(var el in document.getElementsByClassName("foo")){}?
Nearoo

3
for ... ofşimdi olduğu gibi NodeList üzerinde yineleme yapmanızı sağlar for (slide of slides) Distribute(slide). Tarayıcı desteği düzensiz, ancak eğer tercüme ediyorsanız, o for ... ofzaman dönüştürülecektir, ancak NodeList.forEacholmayacaktır.
Mr5o1

74

Yeni querySelectorAll kullanıyorsanız, forEach'i doğrudan arayabilirsiniz.

document.querySelectorAll('.edit').forEach(function(button) {
    // Now do something with my button
});

Aşağıdaki yoruma göre. nodeLists'in forEach işlevi yoktur.

Bunu babel ile kullanıyorsanız, ekleyebilirsiniz Array.fromve düğüm olmayan listeleri forEach dizisine dönüştürecektir. Array.fromaşağıdaki tarayıcılarda yerel olarak çalışmaz ve IE 11 dahil.

Array.from(document.querySelectorAll('.edit')).forEach(function(button) {
    // Now do something with my button
});

Dün geceki buluşmamızda, her biri için olmayan düğüm listelerini ele almanın başka bir yolunu keşfettim.

[...document.querySelectorAll('.edit')].forEach(function(button) {
    // Now do something with my button
});

[...] için Tarayıcı Desteği

Düğüm Listesi olarak gösteriliyor

Düğüm Listesi olarak gösteriliyor

Dizi olarak gösteriliyor

Dizi olarak gösteriliyor


4
Anlaşılan, nodeLists'in her tarayıcıda forEach işlevine sahip olmamasıdır. Prototipleri if ( !NodeList.prototype.forEach ) {NodeList.prototype.forEach = Array.prototype.forEach;}
kurcalamaya istekliysen

Cevabınızı @joshcanhelp'ten gelen yorumla birleştirirsem zarif çözüm. Teşekkürler :) Elbette bu sadece çoklu döngülerde bir hat avantajına yol açacaktır.
yarwest

1
Tüm tarayıcılarda çalışmayabileceği için bundan kaçınmalısınız. İşte kullandığım ve her yerde mükemmel çalışıyor gibi görünen basit bir çözüm: css-tricks.com/snippets/javascript/…
tixastronauta

Sanırım demek [...document.getElementsByClassName('.edit')].forEach(function(button) {
istedin

@ wp-overwatch.com sınıf adında nokta gerekli değildir. Doğru sürüm şu şekilde olmalıdır:[...document.getElementsByClassName('edit')].forEach(function(button) {
MXT

11

Her zaman dizi yöntemlerini kullanabilirsiniz:

var slides = getElementsByClassName("slide");
Array.prototype.forEach.call(slides, function(slide, index) {
    Distribute(slides.item(index));
});

çok güzel ve güzel cevap, çok teşekkür ederim!
Olga Farber

2
Dağıtma nedir?
lesolorzanov

7

Alohci'nin bir canlı olduğu için tersine döngü önerisini takip ettimnodeList . İşte merak edenler için yaptım ...

  var activeObjects = documents.getElementsByClassName('active'); // a live nodeList

  //Use a reverse-loop because the array is an active NodeList
  while(activeObjects.length > 0) {
    var lastElem = activePaths[activePaths.length-1]; //select the last element

    //Remove the 'active' class from the element.  
    //This will automatically update the nodeList's length too.
    var className = lastElem.getAttribute('class').replace('active','');
    lastElem.setAttribute('class', className);
  }

1
 <!--something like this--> 
<html>
<body>



<!-- i've used for loop...this pointer takes current element to apply a 
 particular change on it ...other elements take change by else condition 
-->  


<div class="classname" onclick="myFunction(this);">first</div>  
<div class="classname" onclick="myFunction(this);">second</div>


<script>
function myFunction(p) {
 var x = document.getElementsByClassName("classname");
 var i;
 for (i = 0; i < x.length; i++) {
    if(x[i] == p)
    {
x[i].style.background="blue";
    }
    else{
x[i].style.background="red";
    }
}
}


</script>
<!--this script will only work for a class with onclick event but if u want 
to use all class of same name then u can use querySelectorAll() ...-->




var variable_name=document.querySelectorAll('.classname');
for(var i=0;i<variable_name.length;i++){
variable_name[i].(--your option--);
}



 <!--if u like to divide it on some logic apply it inside this for loop 
 using your nodelist-->

</body>
</html>

0

Yinelemeyle ilgili benzer bir sorun yaşadım ve buraya indim. Belki bir başkası da benim yaptığım hatayı yapıyor.

Benim durumumda, seçici sorun değildi. Sorun, javascript kodunu bozmuş olmamdı: Bir döngüm ve bir alt döngüm vardı. Alt döngü aynı zamanda isayaç olarak da kullanılıyordu j, bu nedenle alt idöngü ana döngünün değerini geçersiz kıldığından , bu ikinci yinelemeye asla ulaşamadı .

var dayContainers = document.getElementsByClassName('day-container');
for(var i = 0; i < dayContainers.length; i++) { //loop of length = 2
        var thisDayDiv = dayContainers[i];
        // do whatever

        var inputs = thisDayDiv.getElementsByTagName('input');

        for(var j = 0; j < inputs.length; j++) { //loop of length = 4
            var thisInput = inputs[j];
            // do whatever

        };

    };
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.