forEach循环,为每个项添加一个类,但每个项的延迟都在增加

时间:2018-01-18 12:20:23

标签: javascript jquery foreach

我试图为一组元素创建一个动画效果并在jquery中成功创建了效果,但我正在尝试学习vanilla javascript并想要一些帮助来翻译我已经拥有的内容:

<div id="vertical-lines">
  <span class="one item"></span>
  <span class="two item"></span>
  <span class="three item"></span>
  <span class="four item"></span>
  <span class="five item"></span>
</div>

这是可以正常使用的jquery。

$('.item').each(function(i){
  setTimeout(function(){
    $('.item').eq(i).addClass('is-visible');
  }, 200 * i);
});

这就是我一直在尝试的但是继续从[i]

返回未定义
var lineItem = document.querySelectorAll('.item'), i
lineItem.forEach(i => {
  setTimeout(function(i){
    console.log(lineItem[i])
    // lineItem[i].className  += "otherclass"
  }, 20)
});

我很感激我对错误的解释!我是javascript的新手,但是到目前为止一直喜欢它,想要了解更多并从错误中吸取教训。

3 个答案:

答案 0 :(得分:1)

Array.prototype.forEach()中,三个参数自动(按顺序)提供:

  1. 引用当前的Array元素
  2. 当前Array元素的索引
  3. 对整个数组的引用。
  4. 我建议您按如下方式重写您的方法:

    var lineItem = Array.from (document.querySelectorAll('.item'))
    lineItem.forEach((arrayElement, index) => {
      setTimeout(function(){
        console.log(lineItem[index]);
        lineItem[index].className  += " otherclass";
     }, 20);
    });
    

    此外,我建议您不要操纵Element.className返回的字符串,而应使用Element.classList.add('otherclass');方法。

答案 1 :(得分:0)

您与setTimeout一起使用的闭包的参数i将是未定义的。 setTimeout不会将任何参数传递给闭包。

.forEach()将当前元素作为第一个参数传递,将索引作为第二个参数传递。

为了将每个项目的延迟增加20ms,您应该使用以下公式:20 * (index + 1)

您的代码应如下所示:

var lineItem = document.querySelectorAll('.item')
lineItem.forEach((item, index) => { // Add item to closure
  setTimeout(() => { // Removed i from closure
    console.log(item) // Console logging item. Could use lineItem[index] instead
    item.className  += "otherclass"
  }, 20 * (index + 1)) // Increase the delay time by 20ms for each item
});

答案 2 :(得分:-1)

为什么不使用递归调用而不是ForEach?

var lineItem = [...document.querySelectorAll('.item')], i = 0;
function delayIt(arr, i) {
    var item = arr.shift();
    setTimeout(() => { 
      console.log(item); 
      arr.length && delayIt(arr, i);
    }, 20 * ++i)
}
delayIt(lineItem, i)