所有
我有一个'信用模块'(类似于游戏中的信用系统),当用户执行操作时,创建一个内部div,其中包含要添加或减去的成本,以便用户可以看到上次操作的成本是多少是
问题:只要函数被调用一次,一切正常,如果用户快速执行多个动作,setTimeout函数(假设为动画&然后删除成本div)就不会被执行。似乎该函数的第二个实例重置了第一个的setTimeout函数。
(function()
{
$("#press").on("click", function(){creditCost(50)});
function creditCost(x)
{
var eParent = document.getElementById("creditModule");
// following code creates the div with the cost
eParent.innerHTML += '<div class="cCCost"><p class="cCostNo"></p></div>';
var aCostNo = document.getElementsByClassName("cCostNo");
var eLatestCost = aCostNo[aCostNo.length - 1];
// following line assigns variable to above created div '.cCCost'
var eCCost = eLatestCost.parentNode;
// cost being assigned
eLatestCost.innerHTML = x;
$(eCCost).animate ({"left":"-=50px", "opacity":"1"}, 250, "swing");
// following code needs review... not executing if action is performed multiple times quickly
setTimeout(function()
{
$(eCCost).animate ({"left":"+=50px", "opacity":"0"}, 250, "swing", function ()
{
$(eCCost).remove();
})
}, 1000);
}
})();
答案 0 :(得分:2)
eParent.innerHTML += '<div class="cCCost"><p class="cCostNo"></p></div>';
是坏线。这会重置元素的innerHTML
,重新创建整个DOM并销毁先前调用中引用的元素 - 让它们的超时失败。有关详细信息,请参阅"innerHTML += ..." vs "appendChild(txtNode)"。你有没有在使用jQuery时使用它?
function creditCost(x) {
var eParent = $("#creditModule");
// Create a DOM node on the fly - without any innerHTML
var eCCost = $('<div class="cCCost"><p class="cCostNo"></p></div>');
eCCost.find("p").text(x); // don't set the HTML if you only want text
eParent.append(eCCost); // don't throw over all the other children
eCCost.animate ({"left":"-=50px", "opacity":"1"}, 250, "swing")
.delay(1000) // of course the setTimeout would have worked as well
.animate ({"left":"+=50px", "opacity":"0"}, 250, "swing", function() {
eCCost.remove();
});
}
答案 1 :(得分:1)
您正在启动动画并安排超时以处理DOM元素,如果用户快速点击,这些元素将在该操作的中间进行修改。您有两种方法可以解决此问题:
您可以通过以下重写和简化代码来实现这两种行为。您可以通过是否包含第一行代码来控制是否获得行为#1或#2。
function creditCost(x) {
// This first line of code is optional depending upon what you want to happen when the
// user clicks rapid fire. With this line in place, any previous animations will
// be stopped and their objects will be removed immediately
// Without this line of code, previous objects will continue to animate and will then
// clean remove themselves when the animation is done
$("#creditModule .cCCost").stop(true, false).remove();
// create HTML objects for cCCost
var cCCost = $('<div class="cCCost"><p class="cCostNo">' + x + '</p></div>');
// add these objects onto end of creditModule
$("#creditModule").append(cCCost);
cCCost
.animate ({"left":"-=50px", "opacity":"1"}, 250, "swing")
.delay(750)
.animate({"left":"+=50px", "opacity":"0"}, 250, "swing", function () {
cCCost.remove();
});
}
})();
请注意,我已从setTimeout()
更改为.delay()
,以便更轻松地停止所有未来的操作。如果你继续使用setTimeout(),那么你需要保存从那里返回的timerID,以便你可以调用clearTimeout()
。使用.delay()
,jQuery为我们做了这个。
答案 2 :(得分:0)
为可能想要使用大多数javascript的人更新了代码。 Jsfiddle, excuse the CSS.
function creditCost(x)
{
var eParent = document.getElementById("creditModule");
var eCCost = document.createElement("div");
var eCostNo = document.createElement("p");
var sCostNoTxt = document.createTextNode(x);
eCCost.setAttribute("class","cCCost");
eCostNo.setAttribute("class","cCostNo");
eCostNo.appendChild(sCostNoTxt);
eCCost.appendChild(eCostNo);
eParent.insertBefore(eCCost, document.getElementById("creditSystem").nextSibling);
$(eCCost).animate ({"left":"-=50px", "opacity":"1"}, 250, "swing");
setTimeout(function()
{
$(eCCost).animate ({"left":"+=50px", "opacity":"0"}, 250, "swing", function ()
{
$(eCCost).remove();
})
}, 1000);
}