在AngularJS ng-repeat下对控制器的函数调用变得无限

时间:2014-08-08 16:23:34

标签: angularjs

我只是想为AngularJS提供一些概念验证。 在下面的代码中,由于某种原因,对getClass的调用将进入无限循环。 范围变量noOfCalls设置为在函数中递增。 我的期望是Angular在每次迭代时调用此函数一次。有人可以帮忙吗?

Plunker链接 http://plnkr.co/edit/7QvkSEQGTJtExwYm9kgD?p=preview

HTML

<body ng-controller="MainCtrl">
<h1>Total number of calls: {{noOfCalls}}</h1>
<div class="container" ng-repeat="item in arraydata">
<div class="form-group">
<input type="text" class={{getClass(item)}} ng-model=item.name />
</div>
</div>
</body>

控制器

var app = angular.module('angularjs-starter', []);

app.controller('MainCtrl', function($scope) {
   $scope.arraydata = [];
   $scope.arraydata.push({id:1, name: "test1"});
   $scope.arraydata.push({id:2, name: "test2"});
   $scope.arraydata.push({id:3, name: "test3"});
   $scope.noOfCalls=0;

   $scope.getClass = function(item)
   {
    $scope.noOfCalls+=1;
    return("form-control");
    }
});

2 个答案:

答案 0 :(得分:2)

评估插值的次数不是您的控制器,而是框架。 Angular在称为摘要周期的过程中多次调用您的函数。此过程用于确定模型是否已更改为绑定的元素。

在您的情况下,您在插值noOfCalls内定义的函数中递增{{getClass()}}。这导致更改noOfCalls变量,该变量再次用于插值{{noOfCalls}}。摘要循环继续运行或重新评估表达式,直到模型稳定或达到10次迭代。在上面的案例中,模型会一次又一次地使用getClass()评估进行更新。

删除插值{{noOfCalls}},迭代不会发生。如果在插值或指令中调用需要评估表达式的函数,请保持函数方面免受影响。

在此处https://docs.angularjs.org/guide/scope

了解开发者指南中的摘要周期

答案 1 :(得分:0)

根本原因是@Chandermani回答所有表达式将重复运行,直到没有检测到任何变化。

仅出于教育目的,如果你真的想做类似的事情,你必须以某种方式找到打破循环的方法。例如。

var childScope = $scope.$new();
childScope.noOfCalls = 0;

$compile($element.find('h1'))(childScope);

$scope.getClass = function(item) {
  setTimeout(function () {
    childScope.noOfCalls++;
    childScope.$digest(); // use $digest here to not trigger digest cycle of parent scopes
  }, 0);

  return("form-control");
};

示例plunker: http://plnkr.co/edit/d4TB6sh4Sc7MP7FrQyOV?p=preview

技巧是:

  1. 创建一个新范围并使用它编译h1标记,并将noOfCalls标记存储在此新范围内。
  2. 使用setTimeout推迟noOfCalls的增量,直到摘要周期结束。
  3. 调用childScope.$digest()更新视图中的h1,但要避免触发父作用域的新摘要周期。