115

div を繰り返し作成したいのですが、アイテムは関数によって返されるオブジェクトです。ただし、次のコードではエラーが報告されます: 10 回の $digest() 反復に達しました。中止します!jsfiddle はこちら: http://jsfiddle.net/BraveOstrich/awnqm/

<body ng-app>
  <div ng-repeat="entity in getEntities()">
    Hello {{entity.id}}!
  </div>
</body>
4

4 に答える 4

198

短い答え:本当にそのような機能が必要ですか、それともプロパティを使用できますか? http://jsfiddle.net/awnqm/1/

長い答え

簡単にするために、オブジェクトの配列の ngRepeat のケースのみを説明します。また、一部省略させていただきます。

AngularJS は、ダーティ チェックを使用して変更を検出します。アプリケーションが開始されると、 に対して実行$digestされ$rootScopeます。スコープの階層$digestに対して深さ優先のトラバーサルを行います。すべてのスコープには、ウォッチのリストがあります。各時計には最後の値があります (最初は)。すべてのウォッチのスコープごとに実行し、現在の値 ( ) を取得して と比較します。現在の値が等しくない場合(常に最初の比較の場合)に設定されます。すべてのスコープが処理されると、から別の深さ優先トラバーサルが開始されます。ダーティ == false またはトラバーサル数 == 10 の場合に終了します。後者の場合、「10 回の $digest() 反復に達しました」というエラーが発生します。記録されます。initWatchVal$digestwatch.get(scope)watch.lastwatch.last$digestdirtytruedirty == true $digest$rootScope$digest

今約ngRepeat。呼び出しごとwatch.getに、コレクションからのオブジェクト ( の戻り値getEntities) を追加情報とともにキャッシュ ( HashQueueMapby hashKey) に格納します。watch.get呼び出しごとに、キャッシュからngRepeatオブジェクトを取得しようとします。hashKeyキャッシュに存在しない場合は、キャッシュにngRepeat保存し、新しいスコープを作成し、オブジェクトを配置し、DOM 要素を作成します

今約hashKey。通常hashKeyは によって生成される一意の番号nextUid()です。しかし、それは関数にすることができます。hashKey生成後、将来の使用のためにオブジェクトに格納されます。

あなたの例がエラーを生成する理由: 関数getEntities()は常に新しいオブジェクトを含む配列を返します。このオブジェクトはキャッシュhashKeyに存在せず、存在しません。ngRepeatそのためngRepeat、それぞれwatch.getが new watch for を使用して新しいスコープを生成し{{entity.id}}ます。この時計は最初watch.getに を持っていwatch.last == initWatchValます。だからwatch.get() != watch.last。というわけ$digestで新たなトラバース開始。そのngRepeatため、新しいウォッチで新しいスコープを作成します。だから... 10回のトラバースの後、エラーが発生します。

修正方法

  1. getEntities()呼び出しごとに新しいオブジェクトを作成しないでください。
  2. 新しいオブジェクトを作成する必要がある場合はhashKey、それらのメソッドを追加できます。例については、このトピックを参照してください。

私が何か間違っている場合は、AngularJS の内部を知っている人が私を訂正してくれることを願っています。

于 2012-09-09T16:26:19.417 に答える
15

これはここで報告され、次の応答を得ました。

あなたのゲッターはべき等ではなく、モデルを変更します(呼び出されるたびに新しい配列を生成することにより)。これは、モデルが最終的に安定することを期待して、Angular にそれを呼び出し続けることを強制していますが、Angular はあきらめて例外をスローすることは決してありません。

ゲッターが返す値は同じですが、同一ではなく、それが問題です。

配列をメイン コントローラーの外に移動すると、この動作がなくなることがわかります。

var array = [{id:'angularjs'}];
function Main($scope) {
    $scope.getEntities = function(){return array;};
};

毎回同じオブジェクトを返すようになったためです。関数の代わりにスコープでプロパティを使用するには、モデルを再構築する必要がある場合があります。

コントローラーのメソッドの結果をプロパティに割り当て、それに対して ng:repeat を実行することで、この問題を回避しました。

于 2012-09-09T13:54:32.273 に答える