2

这段代码有两个输入:div、div(实际上是一个文本框)和目标(一个数字)。然后它会尝试以伪动画的方式增加/减少数字。问题是我使用 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。如果 running 为 true,则该函数将等到它为 false 时继续执行。这会杀死浏览器或达到最大堆栈。

4

1 回答 1

42

几年前的一些小猫:自从你问这个问题以来,你学到了很多东西,特别是关于管理状态和多个事件(更不用说如何正确地提出 StackOverflow 问题)。一个简单的答案是这样的:

var rolling = false;

function rollNum(div, target) {
  if (rolling) { return; }
  rolling = true;

  // Set rolling to false when done
}

这一切都很好,但它忽略了我们滚动时触发的任何事件。上述内容不会适应第一次调整后滑块上所做的更改,但在数字完成滚动之前。现在,我(我们?)会使用 Angular($scope.$watch在这里会派上用场)但是当你在做这个的时候它并不存在。我们为什么不检查滑块上的实时值,而不是传递一个目标数字?(注意使用香草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);
};

其他一些其他变化:

  • if在语句后使用括号。Waaaay 更容易调试
  • 不要忘记 radix 参数parseInt

不幸的是,您没有考虑包含 JSFiddle,因此我无法提供现场演示。

于 2014-05-23T21:39:28.937 回答