.each() 中的 setInterval 仅适用于最后一个间隔?

setInterval inside .each() only working for last interval?

目标:

我正在使用 jQuery 的 each 函数遍历多个 .event 元素。我正在使用来自每个 .event class 内的隐藏跨度元素的信息来计算计时器倒计时。我正在使用 setInterval() 每秒重新计算剩余时间。

问题:

我的所有计算都完美无缺——但只适用于最后一个间隔。每个间隔似乎都覆盖了之前的计算。含义:只有最后一个 .event 甚至得到输出。所有以前的 .event 甚至都没有得到任何输出。使用间隔前后的日志,我能够将错误缩小到 setInterval 函数。如何防止每个间隔覆盖之前的间隔?或者我的错误是在我什至没有想到的地方?

代码:

$('.event').each(function() {
    $event = $(this);

    // SET FUTURE DATE
    $futureDate = $event.find($('.event-time'));
    $countdownDate = new Date($futureDate.text()).getTime();

    setInterval(function() {
    
        // SET TODAYS DATE
        $now = new Date().getTime();
    
        // DIFFERENCE NOW AND FUTURE DATE
        $diff = $countdownDate - $now;
    
        // TIME CALCULATIONS FOR d, h, m, s
        $days = Math.floor($diff / (1000 * 60 * 60 * 24));
        $hours = Math.floor(($diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
        $minutes = Math.floor(($diff % (1000 * 60 * 60)) / (1000 * 60));
        $seconds = Math.floor(($diff % (1000 * 60)) / 1000);
    
        // OUTPUT
        $event.find('.clock .val-d').html($days);
        $event.find('.clock .val-h').html($hours);
        $event.find('.clock .val-m').html($minutes);
        $event.find('.clock .val-s').html($seconds);
    
    }, 1000)
});

问题是因为当你的区间内的函数运行时循环已经完成,所以 $event 只会引用 jQuery 对象中的最后一个 .event 元素。

假设您可以使用 ES6,解决这个问题的简单方法是使用 let 关键字来定义 $event:

$('.event').each(function() {
  let $event = $(this);

  // the rest of your code...
});

如果你不能使用 ES6 那么你需要使用闭包来保留 $(this):

的范围
$('.event').each(function() {
  (function($event) {
    $futureDate = $event.find($('.event-time'));
    $countdownDate = new Date($futureDate.text()).getTime();

    setInterval(function() {
      $now = new Date().getTime();
      $diff = $countdownDate - $now;

      // TIME CALCULATIONS FOR d, h, m, s
      $days = Math.floor($diff / (1000 * 60 * 60 * 24));
      $hours = Math.floor(($diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
      $minutes = Math.floor(($diff % (1000 * 60 * 60)) / (1000 * 60));
      $seconds = Math.floor(($diff % (1000 * 60)) / 1000);

      $event.find('.clock .val-d').html($days);
      $event.find('.clock .val-h').html($hours);
      $event.find('.clock .val-m').html($minutes);
      $event.find('.clock .val-s').html($seconds);
    }, 1000)
  })($(this));
});