$scope
オブジェクトをダーティチェックする
Angular array
は$scope
オブジェクトのウォッチャーをシンプルに維持します。検査$scope
するarray
と、呼び出されたが含まれていることがわかります$$watchers
。
各ウォッチャーは、object
とりわけ、
- ウォッチャーが監視している式。これは単なる
attribute
名前の場合もあれば、もっと複雑なものの場合もあります。
- 式の最後の既知の値。これは、式の現在の計算値に対してチェックできます。値が異なる場合、ウォッチャーは関数をトリガーし、
$scope
ダーティとしてマークします。
- ウォッチャーが汚れている場合に実行される関数。
ウォッチャーの定義方法
AngularJSでウォッチャーを定義するには、さまざまな方法があります。
明示的$watch
にattribute
on することができ$scope
ます。
$scope.$watch('person.username', validateUnique);
{{}}
テンプレートに補間を配置できます(現在のにウォッチャーが作成されます$scope
)。
<p>username: {{person.username}}</p>
ng-model
ウォッチャーを定義するなどのディレクティブを要求できます。
<input ng-model="person.username" />
$digest
サイクルは、彼らの最後の値に対するすべてのウォッチャーをチェックします
通常のチャネル(ng-model、ng-repeatなど)を介してAngularJSとやり取りすると、ディレクティブによってダイジェストサイクルがトリガーされます。
ダイジェストサイクルは、そのすべての子の深さ優先のトラバーサルです$scope
。それぞれについて$scope
object
、繰り返し処理を行い$$watchers
array
、すべての式を評価します。新しい式の値が最後の既知の値と異なる場合、ウォッチャーの関数が呼び出されます。この関数は、DOMの一部を再コンパイルし、の値を再計算し$scope
、をトリガーしAJAX
request
、必要なものを何でも実行できます。
すべてのスコープがトラバースされ、すべての監視式が最後の値に対して評価およびチェックされます。
ウォッチャーがトリガーされると、$scope
ダーティです
ウォッチャーがトリガーされると、アプリは変更があったことを認識し$scope
、ダーティとしてマークされます。
監視関数は$scope
、親または親の他の属性を変更できます$scope
。1つの$watcher
関数がトリガーされた場合、他$scope
のがまだクリーンであることを保証できないため、ダイジェストサイクル全体を再度実行します。
これは、AngularJSに双方向バインディングがあるため、データを$scope
ツリーに戻すことができるためです。$scope
すでに消化されているより高い値を変更する場合があります。おそらく、の値を変更します$rootScope
。
$digest
が汚れている場合は、$digest
サイクル全体を再度実行します
$digest
ダイジェストサイクルがクリーンになるまで(すべての$watch
式は前のサイクルと同じ値になります)、またはダイジェストの制限に達するまで、サイクルをループし続けます。デフォルトでは、この制限は10に設定されています。
ダイジェストの制限に達すると、AngularJSによってコンソールでエラーが発生します。
10 $digest() iterations reached. Aborting!
ダイジェストはマシンでは難しいですが、開発者にとっては簡単です
ご覧のとおり、AngularJSアプリで何かが変更されるたびに、AngularJSは$scope
階層内のすべてのウォッチャーをチェックして、応答方法を確認します。開発者にとってこれは非常に生産性の恩恵です。配線コードをほとんど作成する必要がないので、AngularJSは値が変更されたかどうかに気づき、アプリの残りの部分をその変更に一致させます。
マシンの観点からすると、これは非常に非効率的であり、あまりにも多くのウォッチャーを作成すると、アプリケーションの速度が低下します。Miskoは、アプリが古いブラウザーで遅く感じる前に、約4000人のウォッチャーの数字を引用しています。
この制限は、たとえばng-repeat
大きなものJSON
array
を超えた場合に簡単に到達できます。ウォッチャーを作成せずにテンプレートをコンパイルするワンタイムバインディングなどの機能を使用して、これを軽減できます。
あまりにも多くのウォッチャーを作成しないようにする方法
ユーザーがアプリを操作するたびに、アプリ内のすべてのウォッチャーが少なくとも1回評価されます。AngularJSアプリの最適化の大きな部分は、$scope
ツリー内のウォッチャーの数を減らすことです。これを行う簡単な方法の1つは、1回限りのバインディングです。
ほとんど変更されないデータがある場合は、次のように::構文を使用して一度だけバインドできます。
<p>{{::person.username}}</p>
または
<p ng-bind="::person.username"></p>
バインディングは、含まれているテンプレートがレンダリングされ、データがに読み込まれたときにのみトリガーされ$scope
ます。
これは、ng-repeat
アイテム数が多い場合に特に重要です。
<div ng-repeat="person in people track by username">
{{::person.username}}
</div>