$scope.$watch
と の使い方がわかりません$scope.$apply
。公式ドキュメントは役に立ちません。
具体的にわからないこと:
- それらは DOM に接続されていますか?
- モデルに対する DOM の変更を更新するにはどうすればよいですか?
- それらの間の接続点は何ですか?
このチュートリアルを試してみましたが$watch
、当然の理解が必要$apply
です。
何$apply
をし、何を$watch
し、どのようにそれらを適切に使用するのですか?
$scope.$watch
と の使い方がわかりません$scope.$apply
。公式ドキュメントは役に立ちません。
具体的にわからないこと:
このチュートリアルを試してみましたが$watch
、当然の理解が必要$apply
です。
何$apply
をし、何を$watch
し、どのようにそれらを適切に使用するのですか?
AngularJS を理解するには、AngularJS がどのように機能するかを知っておく必要があります。
何よりもまず、AngularJS はいわゆるダイジェスト サイクルの概念を定義します。このサイクルはループと見なすことができます。その間、AngularJS は、すべてのによって監視されているすべての変数に変更があるかどうかを確認します$scope
。したがって$scope.myVar
、コントローラーで定義し、この変数が監視対象としてマークされているmyVar
場合、ループの各反復で変更を監視するように AngularJS に暗黙的に指示していることになります。
自然なフォローアップの質問は、次のようになります$scope
。幸いなことに、いいえ。内のすべてのオブジェクトの変更を監視すると$scope
、すぐにダイジェスト ループの評価に時間がかかり、すぐにパフォーマンスの問題が発生します。$scope
そのため、AngularJS チームは、いくつかの変数を監視対象として宣言する 2 つの方法を提供してくれました(以下を参照)。
$scope
変数を監視対象として宣言するには、2 つの方法があります。
<span>{{myVar}}</span>
$watch
サービスを介して手動で追加する広告 1) これは最も一般的なシナリオであり、以前に見たことがあると思いますが、これがバックグラウンドで監視を作成していることを知りませんでした。はい、ありました!AngularJS ディレクティブ ( などng-repeat
) を使用すると、暗黙的なウォッチも作成できます。
広告 2) これは、独自の時計を作成する方法です。サービスは、に添付された値が変更さ$watch
れたときにコードを実行するのに役立ちます。$scope
めったに使用されませんが、役立つ場合があります。たとえば、'myVar' が変更されるたびに何らかのコードを実行する場合は、次のようにします。
function MyController($scope) {
$scope.myVar = 1;
$scope.$watch('myVar', function() {
alert('hey, myVar has changed!');
});
$scope.buttonClicked = function() {
$scope.myVar = 2; // This will trigger $watch expression to kick in
};
}
$apply
この機能は統合メカニズムと考えることができます。ご覧のとおり、オブジェクトに直接アタッチされた監視変数$scope
を変更するたびに、AngularJS は変更が発生したことを認識します。これは、AngularJS がこれらの変更を監視することを既に知っているためです。そのため、フレームワークによって管理されるコードで発生した場合、ダイジェスト サイクルは続行されます。
ただし、AngularJS の世界の外で何らかの値を変更し、変更が正常に反映されることを確認したい場合があります。これを考慮してください-jQueryのハンドラー$scope.myVar
内で変更される値があります。$.ajax()
これは、将来のある時点で発生します。AngularJS は、jQuery を待機するように指示されていないため、これが発生するのを待つことができません。
これに取り組むために、$apply
が導入されました。消化サイクルを明示的に開始できます。ただし、これは一部のデータを AngularJS に移行する (他のフレームワークとの統合) 場合にのみ使用する必要があります。AngularJS がエラーをスローするため、この方法を通常の AngularJS コードと組み合わせて使用しないでください。
さて、これですべてがわかったので、もう一度チュートリアルに従う必要があります。$scope
ダイジェスト サイクルは、何も変更がない限り、すべての にアタッチされたすべてのウォッチャーを評価することにより、UI と JavaScript コードの同期を維持します。ダイジェスト ループでそれ以上変更が発生しない場合は、終了したと見なされます。
コントローラーで明示的にオブジェクトをオブジェクトにアタッチする$scope
か{{expression}}
、ビューで直接フォームで宣言することにより、オブジェクトをアタッチできます。
さらなる読み物:
AngularJS では、モデルを更新し、ビュー/テンプレートが DOM を「自動的に」(組み込みまたはカスタム ディレクティブを介して) 更新します。
$apply と $watch はどちらも Scope メソッドであり、DOM とは関係ありません。
概念ページ (セクション「実行時」) には、$digest ループ、$apply、$evalAsync キュー、および $watch リストのかなり適切な説明があります。テキストに添えられた写真は次のとおりです。
スコープにアクセスできるコード (通常はコントローラーとディレクティブ (それらのリンク関数および/またはコントローラー)) は、AngularJS がそのスコープに対して評価する「 watchExpression 」を設定できます。この評価は、AngularJS が $digest ループ (特に、「$watch list」ループ) に入るたびに発生します。個々のスコープ プロパティを監視したり、2 つのプロパティを一緒に監視する関数を定義したり、配列の長さを監視したりできます。
「AngularJS の内部」で何かが起こった場合 – たとえば、AngularJS の双方向データバインディングが有効になっている (つまり、ng-model を使用している) テキストボックスに入力すると、$http コールバックが起動します。 – $apply は既に呼び出されているため、上の図の「AngularJS」の長方形の中にあります。すべての watchExpressions が評価されます (さらに変更が検出されなくなるまで、複数回評価される可能性があります)。
「AngularJS の外部」で何かが発生した場合 (たとえば、ディレクティブで bind() を使用した後にそのイベントが発生し、コールバックが呼び出されたり、jQuery に登録されたコールバックが発生したりする場合)、「ネイティブ」の四角形にとどまっています。コールバック コードが $watch が監視しているものを変更する場合は、$apply を呼び出して AngularJS の四角形に入り、$digest ループを実行します。したがって、AngularJS は変更を認識してその魔法を実行します。
AngularJS は、このevents-loopを拡張して、 と呼ばれるものを作成しますAngularJS context
。
$watch()
UI で何かをバインドするたび$watch
に、$watch
リストに a を挿入します。
User: <input type="text" ng-model="user" />
Password: <input type="password" ng-model="pass" />
ここでは$scope.user
、最初の入力に$scope.pass
バインドされている と、2 番目の入力にバインドされている があります。これを行うと、リストに 2 つの$watch
es が$watch
追加されます。
テンプレートがロードされると、別名リンク段階で、コンパイラはすべてのディレクティブを探し、$watch
必要なすべての es を作成します。
AngularJS は$watch
、$watchcollection
および を提供します$watch(true)
。以下は、ウォッチャーから取得した 3 つすべてを詳細に説明するきちんとした図です。
angular.module('MY_APP', []).controller('MyCtrl', MyCtrl)
function MyCtrl($scope,$timeout) {
$scope.users = [{"name": "vinoth"},{"name":"yusuf"},{"name":"rajini"}];
$scope.$watch("users", function() {
console.log("**** reference checkers $watch ****")
});
$scope.$watchCollection("users", function() {
console.log("**** Collection checkers $watchCollection ****")
});
$scope.$watch("users", function() {
console.log("**** equality checkers with $watch(true) ****")
}, true);
$timeout(function(){
console.log("Triggers All ")
$scope.users = [];
$scope.$digest();
console.log("Triggers $watchCollection and $watch(true)")
$scope.users.push({ name: 'Thalaivar'});
$scope.$digest();
console.log("Triggers $watch(true)")
$scope.users[0].name = 'Superstar';
$scope.$digest();
});
}
$digest
ループブラウザーが AngularJS コンテキストで管理できるイベントを受け取ると、$digest
ループが発生します。このループは、2 つの小さなループで構成されています。1 つは$evalAsync
キューを処理し、もう 1 つは$watch list
. は、私たちが持って$digest
いるリストをループします$watch
app.controller('MainCtrl', function() {
$scope.name = "vinoth";
$scope.changeFoo = function() {
$scope.name = "Thalaivar";
}
});
{{ name }}
<button ng-click="changeFoo()">Change the name</button>
$watch
ng-click はウォッチを作成しないため、ここでは 1 つしかありません。
ボタンを押します。
$digest
すべての $watch に変更が求められます。$watch
$scope.name の変更を監視していた が変更を報告するため、別のループが強制されます$digest
。$digest
ループを実行することです。つまり、入力に文字を書き込むたび$watch
に、このページのすべてをチェックするループが実行されます。イベントが発生したときに呼び出すと$apply
、角度コンテキストを通過しますが、呼び出さないと、その外側で実行されます。それはそれと同じくらい簡単です。$apply
内部でループを呼び出し、$digest()
すべてのウォッチを繰り返し処理して、新しく更新された値で DOM が更新されるようにします。
メソッドはチェーン$apply()
全体でウォッチャーをトリガーしますが、メソッドは現在のウォッチャーとその. 上位のオブジェクトがローカルの変更について知る必要がない場合は、 を使用できます。$scope
$digest()
$scope
children
$scope
$digest()
$watch
、$apply
、$digest
およびダイジェスト サイクルをカバーする非常に詳細なビデオを見つけました。
AngularJS - ウォッチャー、$watch、$watchGroup、$watchCollection、ng-change を理解する
AngularJS - ダイジェスト サイクルの理解 (ダイジェスト フェーズまたはダイジェスト プロセスまたはダイジェスト ループ)
以下は、概念を説明するためにこれらのビデオで使用されている 2 枚のスライドです (念のため、上記のリンクが削除されているか機能していない場合)。
上の画像では、「$scope.c」はどのデータ バインディングでも (マークアップで) 使用されていないため、監視されていません。残りの 2 つ ($scope.a
と$scope.b
) は監視されます。
上の画像から: それぞれのブラウザー イベントに基づいて、AngularJS はイベントをキャプチャし、ダイジェスト サイクルを実行し (すべての変更監視を通過します)、監視機能を実行し、DOM を更新します。$apply
ブラウザ イベントでない場合は、またはを使用してダイジェスト サイクルを手動でトリガーできます$digest
。
$apply
とについての詳細$digest
:
などもあり$watchGroup
ます$watchCollection
。具体的には、キャンバス、 WebGL、またはサーバー要求$watchGroup
の別のビューなど、dom オブジェクトではないビューに複数のプロパティを持つオブジェクトを更新する関数を呼び出す場合に非常に役立ちます。
ここでは、ドキュメントリンク.