无法更新ng-repeat离开动画的范围

时间:2014-12-27 21:26:02

标签: javascript jquery angularjs animation

我在ng-repeat(使用jQuery的animate函数)上有一个角度动画,并希望在每个动画完成时更新模型上的“Visible”属性。目的是编排多个动画。我发现这在enter函数中工作正常,但在leave函数中不起作用。这是代码:

app.animation('.step-animation',
  function () {
    return {
      enter: function (element, done) {
        var scope = angular.element(element).scope();

        jQuery(element).css({ opacity: 0 });
        jQuery(element).animate({
          opacity: 1
        }, 2000, done);

        return function (cancelled) {
          if (cancelled) {
            jQuery(element).stop();
          } else {
            scope.$apply(function () {
              scope.step.Visible = true;
            });
          }
        }
      },
      leave: function(element, done) {
        var scope = angular.element(element).scope();

        jQuery(element).animate({
          opacity: 0
        }, 1000, done);

        return function (cancelled) {
          if (cancelled) {
            jQuery(element).stop();
          } else {
            scope.$apply(function () {
              scope.step.Visible = false;
            });
          }
        }
      }
    }
  });

在输入动画完成后,我的步骤对象上的Visible属性已成功设置为true,但在动画上不会更新。另外 - 我注意到,leave函数中的作用域上的$ parent属性为null,但是在enter函数的作用域中填充了该属性。似乎离开是孤立的,而输入则不是。如何从leave函数更新范围?

更新

我发现return函数在leave函数中被调用两次 - 一次使用cancellation = true。不知道造成这种情况的原因,或者如何排除故障。

1 个答案:

答案 0 :(得分:1)

对于迭代集合中的每个元素,将呈现一个DOM模板,并创建一个新的范围并与之关联。

当从DOM中删除其中一个模板时,会调用代码中的leave函数(例如,由于filter)。删除模板后,其相关范围将被销毁。

这意味着当以下函数执行时,相关的范围已经被销毁:

return function (cancelled) {
  if (cancelled) {
    jQuery(element).stop();
  } else {
    scope.$apply(function () {
      scope.step.Visible = false;
    });
  }
};

您可以通过在其中添加以下内容来验证这一点:

console.log(scope.$$destroyed);

当一个范围被销毁时,其中$apply函数被设置为空函数的事情之一就是:

function noop() {}

这意味着您传递给Visible的匿名函数(将scope.$apply设置为false的函数)永远不会被执行,因为$apply只是一个空函数而且不会用它传递的参数做任何事情。

要解决这个问题,您可以注入$rootScope并使用它代替:

return function(cancelled) {
  if (cancelled) {
    jQuery(element).stop();
  } else {
    $rootScope.$apply(function() {
      scope.step.Visible = false;
    });
  }
};

演示: http://plnkr.co/edit/jdNtcOSzq9BC9vxjmmLy?p=preview

另请注意,element已经是jqLit​​e元素(如果在AngularJS之前加载jQuery,则为jQuery元素),因此您可以替换以下内容:

var scope = angular.element(element).scope();

使用:

var scope = element.scope();

所有出现的事情:

jQuery(element)

只有:

element