.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));
});
目标:
我正在使用 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));
});