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

Ano*_*ous 100 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);                    
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

它似乎只是重复一次.show(),至少我没有那个load()或者.fadeIn()第二次被称为第二次的印象.在.show()得到尽快,因为它已经完成了第一次重复.设置scrollTop动画速度0顺便没有帮助!

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

use*_*654 170

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

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

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


T.J*_*der 155

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

如果提供的start,step,progress,complete,done,fail,和always回调称为对每个元素的基础上 ...

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

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

$("html, body").animate(/*...*/)
    .promise().then(function() {
        // Animation complete
    });
Run Code Online (Sandbox Code Playgroud)

(注意:当问题第一次被问到时,Kevin B 在他的回答中指出了这一点.直到四年后我才注意到它丢失,添加它,然后......然后看到了凯文的回答.请给出答案爱它值得.我认为这是接受的答案,我应该把它留在里面.)

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

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);
  }
});
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

  • 可能因为动画只是html在Webkit中不起作用,而且只是body在Opera中不起作用.使用两者将确保它始终有效,但会在Firefox中触发两次回调.(我可能弄错了浏览器......) (21认同)
  • 我通过创建一个标志处理它:`var ranOne = false; $('body,html').animate({scrollTop:scrollTo},scrollTime,'swing',function(){if(ranOne){... action ... ranOne = false;} else {ranOne = true;它感觉很hacky,但是必须使用"body,html"首先是一种hacky,所以.(抱歉没有换行,猜测评论不显示) (9认同)
  • 是的,这就是原因,实际上我不记得为什么我写过"html,body".是时候重新开始我的大脑了.谢谢 (2认同)
  • IE需要`html`,对于大多数其他浏览器,回调将触发两次.我正在尝试解决同样的问题. (2认同)