使用angular指令会导致错误:达到$ $ digest()迭代。中止

时间:2016-07-12 22:24:10

标签: angularjs angularjs-directive angularjs-scope directive circular-dependency

http://plnkr.co/edit/dBe36L6vwOZOykujFRfg

在plunker中,我得到以下角度误差:" 10 $ digest()迭代达到。中止"!

逻辑在index.html中使用时起作用:

<h1>(working) Fruit from main document: {{vm.randomFruit().name}}</h1>

但是当我尝试使用传入的对象调用指令中的类似代码时抛出错误:

<h1>(causing error) Fruit from directive template: {{fruit.name}}</h1>

如果我只是在范围函数中执行此操作,它似乎也不会在指令中抛出错误:

//this works for both instances
return vm.fruits[0];

但是,当我以任何方式触摸$ scope.fruits时,即使只是复制它,也会导致指令版本上的错误。

//something about touching the array here exposes the error, even though it still works
var x = [];
angular.copy(vm.fruits, x);
return x[0];

为什么会抛出此错误?它似乎是某种类型的循环依赖,但为什么只有指令版?

有没有更好的方法来使用更标准的指令,模板和传入参数对象?

  

错误:达到10 $ digest()次迭代。中止!观察者开除了   最后5次迭代:[[&#34; fn:parentValueWatch;的newval:   {\&#34;名称\&#34;:\&#34;苹果\&#34;}; oldVal:{\&#34; name \&#34;:\&#34; apple \&#34;}&#34;],[&#34; fn:   parentValueWatch; newVal:{\&#34; name \&#34;:\&#34; apple \&#34;}; OLDVAL:   {\&#34; name \&#34;:\&#34; apple \&#34;}&#34;],[&#34; fn:parentValueWatch;的newval:   {\&#34;名称\&#34;:\&#34;苹果\&#34;}; oldVal:{\&#34; name \&#34;:\&#34; apple \&#34;}&#34;],[&#34; fn:   parentValueWatch; newVal:{\&#34; name \&#34;:\&#34; apple \&#34;}; OLDVAL:   {\&#34; name \&#34;:\&#34; apple \&#34;}&#34;],[&#34; fn:parentValueWatch;的newval:   {\&#34;名称\&#34;:\&#34;苹果\&#34;}; oldVal:{\&#34; name \&#34;:\&#34; apple \&#34;}&#34;]]       在错误(本机)       at Object。$ digest(https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:7925:19)       at Object。$ apply(https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:8097:24)       完成后(https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:9111:20)       at completeRequest(https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:9274:7)       在XMLHttpRequest.xhr.onreadystatechange(https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:9244:11

更新1

将aFruit()更新为randomFruit()以更好地展示我的问题:

$scope.randomFruit = function() {
//something about touching the array here exposes the error, even though it still works
var x = [];
angular.copy($scope.fruits, x);
//do some custom stuff here, sorting, etc. <whatever>
var randomIndex = Math.floor((Math.random() * x.length));
return x[randomIndex];
};

更新2

被告知不要使用$ scope,因此将其从控制器中完全删除。仍然看到同样的错误。

myApp.controller('FruitCtrl', function() {
  var vm = this;
  vm.fruits = fruits;

  vm.randomFruit = function() {
    //something about touching the array here exposes the error, even though it still works
    var x = [];
    angular.copy(vm.fruits, x);
    //do some custom stuff here, sorting, etc. <whatever>
    var randomIndex = Math.floor((Math.random() * x.length));
    return x[randomIndex];
  };
});

2 个答案:

答案 0 :(得分:2)

问题在于方法,数据如何传递给Angular。 Angular有很棒的数据绑定,它会检查模型是否已更改并更新UI。更新UI后,它会再次检查下一轮更改。如果数据一直在变化,它就会卡在循环中。

在这种特殊情况下,Angular不理解数据是相同的。它在每个摘要循环上接收新数组,并假设数据已更改,更新UI并再次开始检查。

确保您没有在每个$ digest循环上从UI更新数组,或者在每个$ digest循环上返回新数组。 例如 这将调用无限循环:

$scope.aFruit= function() {
  return [
  {"name":"apple"},
  {"name":"orange"},
  {"name":"banana"},
];
};

这将正常工作,因为对数组的引用保持不变

var myFruits =   return [
      {"name":"apple"},
      {"name":"orange"},
      {"name":"banana"},
    ]    
$scope.aFruit= function() {
    myFruits;
    };

答案 1 :(得分:-1)

哦,好吧! 有两种方法可以做到这一点,但我相信你正在寻找这种方法。

http://plnkr.co/edit/E1y9nqh0DdaHGW2hi4AM?p=preview

问题是你的方法是返回一个对象,但你想获取字符串值。所以我们将方法更改为:

$scope.randomFruit = function() {
  var x = [];
  angular.copy($scope.fruits, x);
  var randomIndex = Math.floor((Math.random() * x.length));
  return x[randomIndex].name;
};

接下来,我们需要更改我们的组件绑定以接受带有&#39; @&#39;

的字符串
bindings: { fruit: '@' },

最后,我们需要在模板中调用方法并使用插值将其设置为我们传递给组件的值:

<show-fruit fruit={{randomFruit()}} />

希望这会有所帮助,还有另一种方法,但如果你想在 模板中调用你的方法 ,那么你就必须这样做。