除非我使用$ timeout,否则AngularJs在指令中制作动画并不起作用

时间:2015-10-27 09:57:30

标签: javascript angularjs animation

我无法弄清楚为什么以下动画无法正常工作:

app.directive('openMenu', ['$animate', '$timeout', function($animate, $timeout) {
    return {
        link: function(scope, elem) {
            elem.bind('click', function() {

                if(elem.is(':animated'))
                    return;

                $timeout(function() {
                    $animate.addClass(elem, 'see');
                }, 0);

            });
        }
    }
}]);

在这一部分中,动画根本不起作用(并且也没有添加类):

app.directive('openMenu', ['$animate', function($animate) {
    return {
        link: function(scope, elem) {
            elem.bind('click', function() {

                if(elem.is(':animated'))
                    return;

                $animate.addClass(elem, 'see');

            });
        }
    }
}]);

在第二个代码片段中,我只删除了$timeout,即0,我尝试使用自动触发功能进行检查 - 动画仅在我使用超时时才有效。有人能解释我为什么吗?

middle {
    margin-left: 0;
}
middle.see {
    margin-left: 270px;
}
.middle.see-add {
    -webkit-transition: margin-left 300ms;
    -moz-transition: margin-left 300ms;
    -ms-transition: margin-left 300ms;
    -o-transition: margin-left 300ms;
    transition: margin-left 300ms;
    margin-left: 0;
}
.middle.see-add.see-add-active {
    margin-left: 270px;
}

这是标记:

<div class="middle" open-menu></div>

3 个答案:

答案 0 :(得分:2)

由于你的指令使用jQuery和jQuery修改DOM,我们需要告诉它有角度。为此,您需要执行$ scope。$ apply但是您会遇到错误:“摘要已在进行中”。

$ timeout内执行的代码保证您的代码将在下一个摘要周期安全执行。

0是默认值,您甚至不需要指定它。你可以简单地写:

 $timeout(function() {
    $animate.addClass(elem, 'see');
 });

$ timeout服务只是一个方便的服务,相当于:

var timeout = setInterval(function(){
    // do stuff
    $scope.$apply();
}, 0); 

您可以在官方文档中找到有关摘要机制的详细信息:https://docs.angularjs.org/error/$rootScope/inprog

答案 1 :(得分:2)

你的问题是你恰好处于Angular生命周期之外。您正在使用.bind,因此只要有变更,Angular就不会收到通知。 $timeout有效,因为它是向Angular通知外部更改的包装器之一。您也可以使用$apply$timeout$apply都采用将要执行的回调。回调完成后,Angular从digest开始rootScope。现在每个绑定都会更新,一切都应该正常工作。

scope.$apply(function() {
    $animate.addClass(elem, 'see');
});

答案 2 :(得分:1)

我认为这是因为elem.bind('click')是一个jQuery函数,它在角度摘要阶段之外运行。

这可能会起作用,而不是使用$timeout

scope.$apply(function() {
     $animate.addClass(elem, 'see');
})'