此代码有两个输入:div,div(实际上是文本框)和target(数字)。然后它将以伪动画的方式尝试输入/减少数字。问题是我使用jQuery滑块作为一种输入形式,在第一次调用完成之前可能会导致多次调用。这不是问题,除非滑块快速增加,然后在增加rollUp完成之前减小,导致永久递减div。我无法弄清楚是什么导致了它。想法?
function rollNum(div, target) {
var contentString = $(div).val();
content = parseInt(contentString.substring(1));
if(content === target)
return;
else if(div !== "#costMinusMSP" && div !== "#savingsWithMSP") {
var total = rollNumTotalCost(div, target);
rollNum("#costMinusMSP", total);
rollNum("#savingsWithMSP", total /*- somehow find the cost here*/)
}
if(isNaN(content))
content = 0;
var remainingChange = target - content;
if(remainingChange > 0)
loopUp();
else
loopDown();
function loopUp() {
var length = remainingChange.toString().length;
var incrementBy = 1;
//Find how far away we are from target
for(var i=0;i<length-1;i++)
incrementBy *= 10;
content += incrementBy;
remainingChange -= incrementBy;
$(div).val("$" + (content))
if(content === target)
return;
else if(content > target) {
$(div).val("$" + (target));
return;
}
setTimeout(loopUp, 60);
}
function loopDown() {
remainingChange = Math.abs(remainingChange);
var length = remainingChange.toString().length;
var decrementBy = 1;
//Find how far away we are from target
for(var i=0;i<length-1;i++)
decrementBy *= 10;
content -= decrementBy;
remainingChange -= decrementBy;
if(content < target) {
$(div).val("$" + (target));
return;
}
//This ensures we won't promise our clients negative values.
if(content <= 0) {
$(div).val("$0");
return;
}
$(div).val("$" + (content))
if(content === target)
return;
setTimeout(loopDown, 60);
}
}
奇怪的是,调整另一个滑块(修改一个不相关的div)可以修复永久的减量。
我尝试过的事情: - 创建函数设置为true的布尔“运行”,然后在返回之前返回false。如果运行是真的,那么函数将等到它为假以继续执行。这会杀死浏览器或达到最大堆栈。
答案 0 :(得分:41)
多年前的几个肯定:自从你提出这个问题以来,你已经学到了很多东西,尤其是关于管理州和国家的问题。多个事件(更不用说如何正确地询问StackOverflow问题)。一个简单的答案是这样的:
var rolling = false;
function rollNum(div, target) {
if (rolling) { return; }
rolling = true;
// Set rolling to false when done
}
这一切都很好但是它忽略了我们在滚动时发生的任何事件。以上不会调整第一次调整后滑块的变化,但是在数字完成滚动之前。现在,我(我们?)会使用Angular($scope.$watch
会在这里派上用场)但是当你正在研究它时它并不存在。为什么我们不检查滑块上的 live 值,而不是传递目标数字? (注意使用vanilla JS,它的很多更快)。
var rollNum = function(textarea) {
var content = parseInt(textarea.value.substring(1), 10)
, target = parseInt(document.getElementById('sliderId').value, 10);
if (content === target) {
return;
}
// Roll up/down logic
setTimeout(function() { rollNum(textarea); }, 60);
};
其他一些misc更改:
if
语句后使用括号。 Waaaay更容易调试parseInt
不幸的是,你没有想过要包含一个JSFiddle,所以我不能提供现场演示。