封闭件损坏 - 请帮我修复它
在相关问题中,我发布了这段代码。它几乎可以工作,但计数器却不能。
我们可以修复它吗? (请不要使用 jQuery)
<script type="text/javascript">
var intervals = [];
var counters = {
"shoes":{"id":"shoe1","minutes":1,"seconds":5},
"trousers":{"id":"trouser1","minutes":10,"seconds":0}
}; // generate this on the server and note there is no comma after the last item
window.onload = function() {
for (var el in counters) { countdown(counters[el]) };
}
function countdown(element) {
intervals[element.id] = setInterval(function() {
var el = document.getElementById(element.id);
var minutes = element.minutes;
var seconds = element.seconds;
if(seconds == 0) {
if(minutes == 0) {
el.innerHTML = "countdown's over!";
clearInterval(intervals[element.id]);
return;
} else {
minutes--;
seconds = 60;
}
}
if(minutes > 0) {
var minute_text = minutes + (minutes > 1 ? ' minutes' : ' minute');
} else {
var minute_text = '';
}
var second_text = seconds > 1 ? 'seconds' : 'second';
el.innerHTML = minute_text + ' ' + seconds + ' ' + second_text + ' remaining';
seconds--;
}, 1000);
}
</script>
shoes: <span id="shoe1"></span><br />
trousers: <span id="trouser1"></span><br />
in a related question I have posted this code. It almost works, but the counter doesn't.
Can we fix it? (no jQuery, please)
<script type="text/javascript">
var intervals = [];
var counters = {
"shoes":{"id":"shoe1","minutes":1,"seconds":5},
"trousers":{"id":"trouser1","minutes":10,"seconds":0}
}; // generate this on the server and note there is no comma after the last item
window.onload = function() {
for (var el in counters) { countdown(counters[el]) };
}
function countdown(element) {
intervals[element.id] = setInterval(function() {
var el = document.getElementById(element.id);
var minutes = element.minutes;
var seconds = element.seconds;
if(seconds == 0) {
if(minutes == 0) {
el.innerHTML = "countdown's over!";
clearInterval(intervals[element.id]);
return;
} else {
minutes--;
seconds = 60;
}
}
if(minutes > 0) {
var minute_text = minutes + (minutes > 1 ? ' minutes' : ' minute');
} else {
var minute_text = '';
}
var second_text = seconds > 1 ? 'seconds' : 'second';
el.innerHTML = minute_text + ' ' + seconds + ' ' + second_text + ' remaining';
seconds--;
}, 1000);
}
</script>
shoes: <span id="shoe1"></span><br />
trousers: <span id="trouser1"></span><br />
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您只需从内部函数中取出
分钟
和秒
变量声明,如下所示:当您调用
countdown
时,您想要获取每个倒计时的初始值,然后慢慢减少它们(闭包确保只要匿名函数需要它们,这些值就保持可用)。您之前所做的就是在每个刻度开始时重置倒计时值,因此倒计时永远没有机会......好吧,倒计时。更新:
如果您需要在倒计时处于活动状态时更新
window.counters
内的值(尽管我不明白您为什么要这样做;如果您想要要对“当前”倒计时值执行任何有意义的操作,只需在匿名函数内执行即可),您只需在末尾添加以下内容即可:You just need to take the
minutes
andseconds
variable declarations out of the inner function, like this:When you call
countdown
, you want to fetch the initial values for each countdown and then slowly decrease them (closure makes sure that the values will stay available as long as the anonymous function requires them). What you were doing before was reset the countdown values at the start of each tick, so the countdown never had a chance to... well, count down.Update:
If you need to update the values inside
window.counters
while the countdowns are active (although I don't see why you would want to do that; if you want to do anything meaningful with the "current" countdown values, just do it inside the anonymous function), you can simply add this at the end:请
在此处检查此工作解决方案。
编辑:脚本有一个小问题。我已经修好了。
重新计算
秒
和分钟
后,您必须将新值设置回element
对象中。Please check this
Working solution is here.
EDIT: There was a minor issue with the script. I've fixed it.
After recalculating the
seconds
andminutes
you have to set the new values back in theelement
object.您在间隔回调中减少了错误的变量。您需要引用
element
成员,而不是执行seconds--
和minutes--
。You're decrementing the wrong variable inside your interval callback. Instead of doing
seconds--
andminutes--
you need to reference theelement
members.到目前为止,您得到的所有答案都无法处理一个简单的事实:
setInterval
在您设置的时间不会可靠地发生。如果浏览器正忙于做其他事情,它可能会被延迟甚至跳过。这意味着您不能依赖更新函数来减少剩余秒数,您将很快开始偏离现实。也许没关系,也许不行。无论如何,都没有必要:只需计算超时发生的时间(例如,“鞋子”计数器从现在起一分零五秒),然后在每次更新时计算超时时间你已经离开了。这样,如果某个时间间隔被删除或发生其他情况,你就不会漂移;你推迟了计算机的时钟。这是一个程序版本:
Live example
这是一个 OOP 版本(使用模块模式,因此
Counter
可以有命名函数和一个私有函数[勾选
]):实例
有关闭包的更多信息请参见此处。
All of the answers you've been given so far fail to handle one simple fact:
setInterval
does not happen reliably at the time you set. It can be delayed or even skipped if the browser is busy doing something else. This means you can't rely on your update function to decrement the number of seconds left, you'll start drifting from reality very quickly. Maybe that's okay, maybe not. There's no need for it, in any case: Just calculate when the timeout occurs (e.g., a minute and five seconds from now for your "shoes" counter), and then at each update, calculate how long you have left. That way if an interval got dropped or something, you won't drift; you're deferring the computer's clock.Here's a procedural version:
Live example
Here's an OOP version (using the module pattern so
Counter
can have named functions and a private one [tick
]):Live example
More about closures here.
我认为,如果您将代码中的超时保留为秒,而不是分钟和秒,它会让您的代码更加简洁,并为您节省一些
if
:(如果它不适用于所有代码...)
I think it'd make your code a lot cleaner and save you some
if
s if you would keep the timeout in code as seconds, rather than minutes and seconds:(I'd post as a comment if it weren't for all the code...)