[英]AngularJs animating in directive doesn't work unless i use $timeout
I can't figure out why the following animation doesn't work as it should: 我不知道为什么以下动画无法正常工作:
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);
});
}
}
}]);
And in this one the animation doesn't work at all (and class is not added either): 而且在这一动画中根本不起作用(也没有添加类):
app.directive('openMenu', ['$animate', function($animate) {
return {
link: function(scope, elem) {
elem.bind('click', function() {
if(elem.is(':animated'))
return;
$animate.addClass(elem, 'see');
});
}
}
}]);
In the second code snippet I only removed $timeout
, which is 0, I tried to use self-firing functions to check - animating works only when I am using timeouts. 在第二个代码片段中,我仅删除了
$timeout
,它是0,我尝试使用自触发函数进行检查-仅当我使用超时时,动画才有效。 Can someone explain me why? 有人可以解释我为什么吗?
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;
}
Here is the markup: 这是标记:
<div class="middle" open-menu></div>
Since your directive uses jQuery and jQuery modify the DOM, we need to tell angular about it. 由于您的指令使用jQuery且jQuery修改了DOM,因此我们需要对它进行介绍。 To do so, you need to do $scope.$apply but you would run into the error : "digest already in progress".
为此,您需要执行$ scope。$ apply,但是会遇到错误:“消化已在进行中”。
The code executed inside the $timeout guarantee that your code will be safely executed on the next digest cycle. 在$ timeout内部执行的代码保证了您的代码将在下一个摘要周期安全地执行。
0 is the default value, you don't even need to specify it. 默认值为0,甚至不需要指定它。 You could simply write :
您可以简单地写:
$timeout(function() {
$animate.addClass(elem, 'see');
});
The $timeout service is simply a convenient service equivalent to : $ timeout服务只是一个便捷的服务,等效于:
var timeout = setInterval(function(){
// do stuff
$scope.$apply();
}, 0);
You can find extensive information about the digest mechanism in the official documentation : https://docs.angularjs.org/error/$rootScope/inprog 您可以在官方文档中找到有关摘要机制的大量信息: https : //docs.angularjs.org/error/$rootScope/inprog
Your problem is that you happen to be out of the Angular life-cycle. 您的问题是您碰巧不在Angular生命周期内。 You are using
.bind
so Angular will not be notified whenever something has changed. 您使用的是
.bind
因此只要发生更改,Angular都不会收到通知。 The $timeout
works because it's a one of the wrappers to notify Angular about an outside change. $timeout
之所以有效,是因为它是将外部更改通知Angular的包装器之一。 You could also use $apply
. 您也可以使用
$apply
。 Both, the $timeout
and $apply
take a callback which will be executed. $timeout
和$apply
都将执行一个回调。 After the callback is finished Angular starts a digest
beginning at the rootScope
. 回调完成后,Angular从
rootScope
开始开始digest
。 Now every binding will be updated and everything should work properly. 现在,每个绑定都将更新,并且所有内容都应正常运行。
scope.$apply(function() {
$animate.addClass(elem, 'see');
});
I think it's because elem.bind('click')
is a jQuery function, which is running outside of the angular digest phase. 我认为这是因为
elem.bind('click')
是一个jQuery函数,它在角度摘要阶段之外运行。
Probably this would work as well instead of using $timeout
: 也许这也可以使用
$timeout
代替:
scope.$apply(function() {
$animate.addClass(elem, 'see');
})'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.