【问题标题】:AngularJS: $rootScope:infdig error when calling a ng-style function inside ng-repeatAngularJS:在 ng-repeat 中调用 ng 样式函数时出现 $rootScope:infdig 错误
【发布时间】:2015-09-23 01:11:00
【问题描述】:

我正在尝试在一些短语上构建动画,这些短语将显示在网站主页上,随机位置并带有淡入淡出和翻译效果。

我会使用 ng-repeat 属性中的 ng-style 属性并设置调用 HomeController 中定义的 JavaScript 函数的 ng-style 值来实现这一点。 p>

使用此方法会导致 Angular 抛出异常:$rootScope:infdig 错误 10 $digest() 迭代已达到。中止!在最后 5 次迭代中触发的观察者

我阅读了很多关于此的内容,但没有解决方案可以解决我的问题。 谁能帮帮我?

这里是 index.html 的一部分:

<div class="phrasesContainer" animate-phrases="">
      <h3 class="flying-text" ng-repeat="phrase in Phrases" ng-style="getTopLeftPosition()">{{phrase}}</h3>
    </div>

这里是控制器功能:

$scope.getTopLeftPosition = function() {
var top = randomBetween(10, 90);
var left = getRandomTwoRange(5, 30, 70, 80);

return {
  top: top + '%',
  left: left + '%'
};

}

这是一个演示:http://plnkr.co/edit/8sYks589agtLbZCGJ08B?p=preview

【问题讨论】:

  • getTopLeftPosition() 在每个摘要上都被调用,因为它永远不会稳定。它总是返回不同的值。为什么不将样式相关的代码移到你的指令中?

标签: javascript jquery angularjs ng-style angularjs-rootscope


【解决方案1】:

@Hieu Le 暗示了这个问题,但你的问题是,由于你总是在你的 getTopLeftPosition 函数中返回一个随机位置,所以每次都会调用 angularjs 摘要循环以实际将更改传播给观察者。这导致它不断地跑来跑去。

你可以做的是预先计算你的随机位置,然后在你的 html 中使用它。

例如,在您的激活函数中,您可以执行以下操作:

  function activate() {
    $scope.Phrases = ["Phrase 1", "Phrase 2", "Phrase 3", "Phrase 4", "Phrase 5", "Phrase 6"];
    $scope.PhrasesAndPositions = $scope.Phrases.map(function(phrase){
      return {
        phrase: phrase,
        position: getTopLeftPosition()
      }
    });
  }

然后你可以把你的 html 改成这样:

    <div class="phrasesContainer" animate-phrases="">
      <h3 class="flying-text" ng-repeat="pap in PhrasesAndPositions" ng-style="pap.position">{{pap.phrase}}</h3>
    </div>

这里是我的更改的工作 plunk:http://plnkr.co/edit/FD9hYX9Q5wUkW2q7y86M?p=preview

【讨论】:

  • 我认为 OP 希望一个短语每次重新出现时都有一个新的位置。虽然从问题中不清楚。不错的答案!
  • 很好的建议@JoseM,这个解决方案的问题是它消除了位置的随机性。当它再次重复时,所有短语将具有相同的位置并且不是随机的
  • 谢谢!这个解决方案解决了我的问题!! @Hieu Le 另外,我的解决方案不会在每次迭代时设置随机位置(因为 ingdig 异常)。然而,Anid Monsur 解决方案允许这种行为。我不能同时接受这两个答案,但我愿意 (stackoverflow.com/questions/32721766/…)
【解决方案2】:

这是一个解决方案,我将您的样式生成移到指令中。在显示元素之前设置位置。由于这是 CSS 更改,因此我也修改了样式,以使位置不会转换。

这是指令。我排除的代码没有改变:

app.directive('animatePhrases', function() {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      setTimeout(function() {
        ...
      }, 1000);

      function changeText() {
        var currentActive = $('.phrasesContainer .active');
        var nextActive = currentActive.next();
        currentActive.toggleClass('active');

        if (nextActive.length == 0)
          nextActive = $('.phrasesContainer .flying-text').first();

        nextActive.css(getTopLeftPosition()); // Add this
        nextActive.toggleClass('active');

        setTimeout(changeText, 5000);
      }

      function getTopLeftPosition() {
        ...
      }

      function getRandomTwoRange(firstStart, firstEnd, secondStart, secondEnd) {
        ...
      }

      function randomBetween(min, max) {
        ...
      }
    }
  };
});

CSS:

.flying-text {
    transition: opacity 2s ease-in-out, margin 2s ease-in-out;
    position: absolute;
    opacity: 0;
    font-size: 1.5em;
}

在您的 HTML 中,只需删除 ng-style

Plunker:http://plnkr.co/edit/bZB3A5hD7Bc4r4pp1g7V?p=preview

【讨论】:

  • 谢谢!我将使用该解决方案,控制器更清洁 :) @JoseM 解决方案也解决了我的问题(stackoverflow.com/questions/32721766/…),它不允许每次迭代时出现随机性,但如果您只希望在开始时随机位置,它仍然是一个很好的解决方案!
【解决方案3】:

这样你就可以管理你的 ng 风格

$scope.getTopLeftPosition = function() {
$scope.top = randomBetween(20, 90);
$socpe.left = getRandomTwoRange(5, 30, 70, 80);

}

function getRandomTwoRange(firstStart, firstEnd, secondStart, secondEnd) {
var isLower = (Math.random() * 2) < 1;
if (isLower)
  return randomBetween(firstStart, firstEnd);
else
  return randomBetween(secondStart, secondEnd);
}

function randomBetween(min, max) {
 return Math.floor(Math.random() * (max - min + 1)) + min;
}


<body>
<div ng-controller="HomeController">
  <div class="row" style="height:100%">
    <div class="phrasesContainer" animate-phrases="">
      <h3 class="flying-text " ng-repeat="phrase in Phrases" ng-style="{ 'top' : top, 'left' : left }">{{phrase}}</h3>
    </div>
  </div>
</div>

【讨论】:

  • 请解释您的解决方案。
  • $scope.getTopLeftPosition 在哪里被调用?
  • 使用作用域而不是调用函数我猜你可以解决你的问题。
【解决方案4】:

我认为问题在于你不能像那样绑定 ng-style。它认为它需要不断地调用getTopLeftPosition。

我在这里得到了一些工作。时间有点偏,但没有更多错误。这里我使用 $interval 来重复一些事情:

请在此处查看:http://plnkr.co/edit/B4iMZXMvZFoYMCKNvVrc?p=preview

  $scope.phrase_style = getTopLeftPosition();

  function change_phrase_style() {
      $scope.phrase_style = getTopLeftPosition();
  }

  function start_interval() {
      change_phrase_style();
      $interval(function(){
          change_phrase_style();
      }.bind(this), 5000); 
  }

  setTimeout(start_interval, 1000);

这也可能是相关的:angularjs infinite $digest Loop when no scope changes

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-22
    • 1970-01-01
    • 2013-11-23
    • 2017-06-20
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    相关资源
    最近更新 更多