如何按顺序运行很多功能?

时间:2015-07-02 06:46:42

标签: javascript jquery jquery-deferred q

也许这个问题是重复的。我发现了很多类似的问题,但没有人能真正解决我的问题。这是我的任务:

function animate(){
  $ul.each(function(){
     $(this).find('li').each(function(){
          //animate block
          $(this).animate({top:'-100%'},100,function(){
             $(this).css({top:'100%'});
          });
          //endblock
        });
     });
}

正如您所知,'动画块'函数将同时运行。我希望他们按顺序运行。我怎样才能做到这一点?

我已经阅读了jQuery' deferred',' Q'关联文章,但仍然令人困惑。

抱歉我的英文。

---------此外------

如果我想多次运行动画功能,我该怎么办?

4 个答案:

答案 0 :(得分:1)

使用queue()函数检查此解决方案。

此功能等待动画完成,然后执行它的内容。

var anim = function(i) {
  $('.test').eq(i).animate({'top':'20px'}, 350).queue(function() {
    i++;
    anim(i);
    $(this).dequeue();
  });
}
anim(0);
.test {
  width:50px;
  height:50px;
  float: left;
  margin-right:10px;
  background-color:green;
  position:relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="test">test</div>
<div class="test">test</div>
<div class="test">test</div>
<div class="test">test</div>
<div class="test">test</div>
   

答案 1 :(得分:0)

这样的事情应该有效:

var last_deferred = $.Deferred();
last_deferred.resolve();

$ul.each(function(){
    $(this).find('li').each(function(){
         var deferred = $.Deferred(),
             $that = $(this);
         last_deferred.then(function() {
             $that.animate({top:'-100%'},100,function(){
                $(this).css({top:'100%'});
                deferred.resolve();
             });
         });
         last_deferred = deferred;
    });
});

说明:我在这里使用了延迟对象.then.resolve的两个重要功能。当您致电.resolve();时,延迟对象将通过.then触发分配给它的所有处理程序。所以会发生的事情是我首先定义&#34; dummy&#34;推迟我立即解决。如果解析了延迟对象,则通过.then添加处理程序将自动使其运行。那么会发生什么呢

  1. last_deferred已定义并已解决
  2. 创建了临时deferred
  3. .then处理程序添加到last_deferred
  4. .then处理程序被触发,在执行某些操作后,它会解析deferred(从而在.then上触发deferred
  5. last_deferred被重新定义为deferred
  6. 回到2。
  7. 所以这是一种异步循环(因为.animate是异步操作)。在每个步骤中,您说&#34;当前一个deferred被解析时,告诉它解决下一个&#34;。

答案 2 :(得分:0)

如果你想避免jQuery的笨拙.queue() / .dequeue(),那么你可以从<li>元素的jQuery集合构建一个promise链。

function animate($ul) {
    var p = $.when(); //resolved starter promise
    $("li", $ul).each(function(i, li) {
        p = p.then(function() {
            return $(li).animate({ top:'-100%' }, 100, function() {
                return $(li).css({ top:'100%' });
            }).promise();
        });
    });
    return p;
}

随着链的稳定,动画将按顺序发生。

更优雅的是,您可以将jQuery扩展为.reduce()方法,从Array.prototype采用。

jQuery.fn.reduce = Array.prototype.reduce;

然后,通过在jQuery集合上调用.reduce()来构建所需的promise链。

function animate($ul) {
    return $("li", $ul).reduce(function(p, li) {//wow, jQuery has a .reduce() method!
        return p.then(function() {
            //Here, perform the required animation and return a promise of its completion.
            return $(li).animate({top:'-100%'}, 100, function() {
                $(li).css({top:'100%'});
            }).promise();
        });
    }, $.when());//Resolved starter promise, ie p in the first iteration of .reduce() .
}

这种模式非常值得学习,因为它有很多应用程序。

在这两个示例中,最外面的return允许您在调用.then()的地方链animate()

animate($("ul")).then(function() {
    //do something when all the <li> animations have completed.
});

答案 3 :(得分:0)

尝试使用.queue()$.map().delay();在window.innerHeight代替100px单位代替%单位;在.animate()回拨

替换.animate代替.css

&#13;
&#13;
complete
&#13;
var ul = $("ul");
ul.queue("_fx", $.map(ul.find("li"), function(el, i) {
  return function(next) {
    return $(el).animate({
      top: "-" + window.innerHeight / 10 + "px"
    }, 100, function() {       
      $(this).delay(100).animate({
        top: window.innerHeight - $(this).height() * 1.5 + "px"
      }, 100, next);
    })
  };
})).dequeue("_fx");
&#13;
body {
  height: 200px;
}
ul li {
  top: 150px;
  position: relative;
  width: 50px;
  height: 50px;
  background: red;
  padding 8px;
  display: inline-block;
}
&#13;
&#13;
&#13;