$animate.removeClass 没有 $evalAsync inside 指令就不能工作?

$animate.removeClass not working without $evalAsync inside directive?

我创建了一个在模型更改时淡出和淡入视图的指令。

app.controller('myCtrl', function($scope, $interval) {
  $scope.number = 0;
  $interval(function() {
    $scope.number++;
  }, 1000);
});

app.directive('fadeOnChange', function($timeout, $animate) {
  return {
    restrict: 'E',

    //We output the value which will be set between fades
    template: '{{theFadedValue.nv}}',

    link: function(scope, elem, attr) {
      //The scope variable we will watch
      var vtw = attr.valueToWatch;

      //We add the anim class to set transitions
      $animate.addClass(elem, 'anim');

      //We watch the value 
      scope.$watch(vtw, function(nv) {

        //we fade out
        var promise = $animate.addClass(elem, 'fade-it-out');

        //when fade out is done, we set the new value
        promise.then(function() {

          scope.$evalAsync(function() {
             scope.theFadedValue = {"nv": nv};
            //we fade it back in
            $animate.removeClass(elem, 'fade-it-out');
          });
        });
      })
    }
  };
});

这是风景

<div ng-controller="myCtrl">
  <h1><fade-on-change value-to-watch="number"></fade-on-change></h1>
</div>

它工作得很好,但我想了解为什么我需要使用 $apply、$digest、$timeout 或 $evalAsync 来包装我对 $animate.removeClass 的调用才能工作?如果我不这样做,class 就不会被删除(这让我今天下午很头疼)。

我对这四种方法很感兴趣,也明白它们有何不同,但在这种情况下需要使用其中一种方法让我很困惑。

plunker

基本上,异步方法不会 运行 $digest 直接循环。($http 的例外情况,因为它内部包装在 $scope.$apply() 中)

在您的情况下,您正在等待异步的完整承诺。这就是为什么你可以使用 $timeout(function(){ })$evalAsync,这个 angular 服务包装在 $scope.$apply()$scope.$apply() 内部 运行 摘要周期和所有范围变量得到更新。

$evalAsync run after the DOM has been manipulated by Angular, but before the browser renders

Link here 了解有关何时使用 $scope.$apply()

的更多信息

希望这会消除您的疑虑。谢谢。