.animate()的回调被调用两次jquery

时间:2012-01-09 15:26:40

标签: jquery callback

由于我添加了一些scrollTop - 动画,我的回调的某些部分会被调用两次:

$('html, body').animate({scrollTop: '0px'}, 300,function() {
    $('#content').load(window.location.href, postdata, function() {                 
        $('#step2').addClass('stepactive').hide().fadeIn(700, function() {
            $('#content').show('slide',800);                    
        });
    });
});

似乎只重复.show(),至少我没有第二次调用load().fadeIn()的印象。 .show()第一次完成后会立即重复。将scrollTop动画速度设置为0并没有帮助!

我认为它与动画队列有关,但我无法弄清楚如何找到解决方法,特别是为什么这种情况正在发生。

2 个答案:

答案 0 :(得分:166)

要获得完成多个元素动画的单个回调,请使用延迟对象。

$(".myClass").animate({
  marginLeft: "30em"
}).promise().done(function(){
  alert("Done animating");
});

有关PromiseDeferred Objects的详细说明,请参阅jQuery API。

答案 1 :(得分:150)

animate在您调用animate的集合中为每个元素调用一次回调:

  

如果提供,startstepprogresscompletedonefailalways回调在每个元素的基础上调用 ...

由于您要为两个元素(html元素和body元素)设置动画,因此您将获得两个回调。 (对于任何想知道为什么 OP为两个元素设置动画的人,这是因为动画在某些浏览器上body上运行,但在其他浏览器上html上运行。)

要在动画完成时获取单个回调,animate文档会指向您使用promise方法获取动画队列的承诺,然后使用then对回调进行排队:

$("html, body").animate(/*...*/)
    .promise().then(function() {
        // Animation complete
    });

(注意:Kevin B在第一次提出这个问题时指出了in his answer。直到四年后我才注意到它丢失了,添加了它,然后......凯文的回答。请给出他应得的爱的答案。我认为这是接受的答案,我应该留下来。)

这是一个显示单个元素回调和整体完成回调的示例:

jQuery(function($) {

  $("#one, #two").animate({
    marginLeft: "30em"
  }, function() {
    // Called per element
    display("Done animating " + this.id);
  }).promise().then(function() {
    // Called when the animation in total is complete
    display("Done with animation");
  });

  function display(msg) {
    $("<p>").html(msg).appendTo(document.body);
  }
});
<div id="one">I'm one</div>
<div id="two">I'm two</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>