在jquery插件中添加done()函数,等待动画结束

时间:2014-04-28 19:10:04

标签: jquery plugins promise jquery-deferred deferred

我的问题是当我添加:

.done(function() {
  innerDef.resolve();                    
});

在#34; animate"功能,它不能按我的意愿工作。
我只是希望函数等到动画结束,如下所示:

$('#anim_vision').showThis().done(function(){
   alert('task finished!');
});

我的完整插件代码:

(function ($) {

    $.fn.extend({    
        showThis: function (options) {    
            var def = $.Deferred();

            var options = $.extend(options);
            var deferredList = [];

            this.each(function () { 
                var innerDef = $.Deferred();
                deferredList.push(innerDef.promise());

                $( this )
                .children('.texto')
                .removeClass('opacity_none')
                .css('display','block');

                $( this )
                .animate({'height':'100%'}, 900, 'easeOutQuad')
                .done(function() {
                    innerDef.resolve();                    
                });
                });

            $.when.apply($, deferredList).done(function() {
               def.resolve(); 
            });

            return def.promise();
        }
    });
})(jQuery);

我真的需要帮助!

1 个答案:

答案 0 :(得分:6)

常规jQuery对象没有.done()方法。您需要通过更改以下内容来调用.promise()来获取动画的promise对象:

            .animate({'height':'100%'}, 900, 'easeOutQuad')
            .done(function() {
                innerDef.resolve();                    
            });

到此:

            .animate({'height':'100%'}, 900, 'easeOutQuad')
            .promise()
            .done(function() {
                innerDef.resolve();                    
            });

但是,您可以直接使用承诺来简化事情,而不是自己制作innerDef


进一步简化事情,你也不需要自己推迟,因为你可以从$.when()返回承诺:

(function ($) {

    $.fn.extend({    
        showThis: function (options) {    
            var options = $.extend(options);
            var promiseList = [];

            this.each(function () { 

                $( this )
                    .children('.texto')
                    .removeClass('opacity_none')
                    .css('display','block');

                // run the animation,
                // get a promise object for the animation queue,
                // put it in our list of promises
                promiseList.push(
                     $( this )
                     .animate({'height':'100%'}, 900, 'easeOutQuad')
                     .promise()
                );
            });

            // return a new promise that is resolved 
            // when all the animations are done
            return $.when.apply($, promiseList);
        }
    });
})(jQuery);

经过进一步研究,您可以更加简化:

jQuery.fn.extend({    
    showThis: function () {    
        return (this
          .children('.texto')
          .removeClass('opacity_none')
          .css('display','block')
          .animate({'height':'100%'}, 900, 'easeOutQuad')
          .promise()
        );
    }
});

进一步的变化:

  1. 您调用的所有jQuery方法都已迭代整个集合,因此您无需使用this.each()手动迭代它们。
  2. 您没有使用options参数,因此您可以删除它。
  3. 你没有任何持久的状态变量,所以你不需要它周围的函数包装来隔离它们。
  4. jQuery的.promise()会在整个集合完成动画时解析,因此它可以帮助您。您不需要自己的$.when()或自己的promise数组。您只需返回.promise()之后的.animate(),它就会在所有动画完成时解析。
  5. 您可以看到此演示,了解.promise()如何等待整个集合制作动画:http://jsfiddle.net/jfriend00/Erq5Q/