如何正确迭代getElementsByClassName

时间:2022-09-23 07:42:54

I am Javascript beginner.

我是Javascript初学者。

I am initing web page via the window.onload, I have to find bunch of elements by their class name (slide) and redistribute them into different nodes based on some logic. I have function Distribute(element) which takes an element as input and does the distribution. I want to do something like this (as outlined for example here or here):

我通过window.onload启动网页,我必须通过他们的类名(幻灯片)找到一堆元素,并根据一些逻辑将它们重新分配到不同的节点。我有函数Distribute(element),它接受一个元素作为输入并进行分发。我想做这样的事情(例如这里或这里所概述的):

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

however this does not do the magic for me, because getElementsByClassName does not actually return array, but a NodeList, which is...

但是这对我来说并不神奇,因为getElementsByClassName实际上并不返回数组,而是一个NodeList,它是...

...this is my speculation...

......这是我的推测......

...being changed inside function Distribute (the DOM tree is being changed inside this function, and cloning of certain nodes happen). For-each loop structure does not help either.

...在函数内部进行更改Distribute(在此函数内部正在更改DOM树,并且会发生某些节点的克隆)。 For-each循环结构也没有帮助。

The variable slides act's really un-deterministicaly, through every iteration it changes it's length and order of elements wildly.

变量幻灯片的行为确实是非确定性的,通过每次迭代,它都会大大改变元素的长度和顺序。

What is the correct way to iterate through NodeList in my case? I was thinking about filling some temporary array, but am not sure how to do that...

在我的情况下迭代NodeList的正确方法是什么?我在考虑填充一些临时阵列,但我不知道该怎么做......

EDIT:

important fact I forgot to mention is that there might be one slide inside another, this is actually what changes the slides variable as I have just found out thanks to user Alohci.

我忘了提到的一个重要事实是,在另一个内部可能有一个幻灯片,这实际上是因为我刚刚发现感谢用户Alohci而更改了幻灯片变量。

The solution for me was to clone each element into an array first and pass the array ono-by-one into Distribute() afterwards.

我的解决方案是先将每个元素克隆到一个数组中,然后逐个将数组传递给Distribute()。

5 个解决方案

#1


65  

According to MDN, the way to retrieve an item from a NodeList is:

根据MDN,从NodeList检索项目的方法是:

nodeItem = nodeList.item(index)

Thus:

从而:

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

I haven't tried this myself (the normal for loop has always worked for me), but give it a shot.

我自己没有尝试过(正常的循环一直对我有用),但请试一试。

#2


26  

If you use the new querySelectorAll you can call forEach directly.

如果您使用新的querySelectorAll,则可以直接调用forEach。

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

Per the comment below. nodeLists do not have a forEach function.

根据以下评论。 nodeLists没有forEach函数。

If using this with babel you can add Array.from and it will convert non node lists to a forEach array. Array.from does not work natively in browsers below and including IE 11.

如果使用babel你可以添加Array.from,它会将非节点列表转换为forEach数组。 Array.from在以下浏览器中无法正常工作,包括IE 11。

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

#3


8  

You could always use array methods:

你总是可以使用数组方法:

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

#4


7  

I followed Alohci's recommendation of looping in reverse because it's a live nodeList. Here's what I did for those who are curious...

我遵循Alohci建议的反向循环,因为它是一个实时的nodeList。这就是我为那些好奇的人所做的......

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

#5


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>

#1


65  

According to MDN, the way to retrieve an item from a NodeList is:

根据MDN,从NodeList检索项目的方法是:

nodeItem = nodeList.item(index)

Thus:

从而:

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

I haven't tried this myself (the normal for loop has always worked for me), but give it a shot.

我自己没有尝试过(正常的循环一直对我有用),但请试一试。

#2


26  

If you use the new querySelectorAll you can call forEach directly.

如果您使用新的querySelectorAll,则可以直接调用forEach。

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

Per the comment below. nodeLists do not have a forEach function.

根据以下评论。 nodeLists没有forEach函数。

If using this with babel you can add Array.from and it will convert non node lists to a forEach array. Array.from does not work natively in browsers below and including IE 11.

如果使用babel你可以添加Array.from,它会将非节点列表转换为forEach数组。 Array.from在以下浏览器中无法正常工作,包括IE 11。

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

#3


8  

You could always use array methods:

你总是可以使用数组方法:

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

#4


7  

I followed Alohci's recommendation of looping in reverse because it's a live nodeList. Here's what I did for those who are curious...

我遵循Alohci建议的反向循环,因为它是一个实时的nodeList。这就是我为那些好奇的人所做的......

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

#5


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>