回答:
AngularJSを理解するには、AngularJSがどのように機能するかを知っておく必要があります。
何よりもまず、AngularJSはいわゆるダイジェストサイクルの概念を定義しています。このサイクルはループと見なすことができ、その間、AngularJSはすべてのsが監視するすべての変数に変更があるかどうかをチェックします$scope
。したがって$scope.myVar
、コントローラーで定義し、この変数が監視対象としてマークされている場合、AngularJSにmyVar
ループの各反復での変更を監視するように暗黙的に指示しています。
自然なフォローアップの質問は次のようになり$scope
ます。幸い、そうではありません。内のすべてのオブジェクトへの変更を監視する場合$scope
、ダイジェストループをすぐに評価するには時間がかかり、パフォーマンスの問題がすぐに発生します。そのため、AngularJSチームは、いくつかの$scope
変数を監視対象として宣言する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の世界外で値を変更して、変更が正常に伝播することを確認したい場合があります。これを検討してください$scope.myVar
-jQueryの$.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が評価されます(おそらく2回以上–変更が検出されなくなるまで)。
「AngularJSの外で」何かが発生した場合(たとえば、ディレクティブでbind()を使用した後、そのイベントが発生し、コールバックが呼び出されるか、jQueryで登録されたコールバックが発生します)、まだ「ネイティブ」の長方形にいます。コールバックコードが$ watchが監視しているものを変更する場合は、$ applyを呼び出してAngularJSの四角形に入り、$ digestループが実行されるようにします。これにより、AngularJSが変更に気付き、その魔法を実行します。
scope.$apply(scope.model)
していますが、どのデータが転送され、どのようにモデルの適切な場所に転送されるのか理解できません。
scope.$apply(scope.model)
単にscope.model
Angular式として評価され、$ digestループに入ります。あなたが参照する記事scope.$apply()
では、モデルがすでに$ watchされているので、おそらく十分でしょう。stop()関数がモデルを更新していて(toUpdateはscope.modelへの参照であると思います)、次に$ applyが呼び出されます。
$watch
ページがなく、2番目のリンクは壊れています-現在のところ、とにかく)。悲しいことに、アーカイブバージョンは、コンテンツを作成した非同期プロセスをキャッシュしませんでした。
AngularJSはこのイベントループを拡張し、という名前を作成しますAngularJS context
。
$ watch()
UIで何かをバインドするたび$watch
に、$watch
リストにを挿入します。
User: <input type="text" ng-model="user" />
Password: <input type="password" ng-model="pass" />
ここにあります $scope.user
、最初の入力に$scope.pass
バインドされていると、2番目の入力にバインドされているがあります。これにより、2つの$watch
esが$watch
リストに追加されます。
私たちの場合はテンプレートがロードされ、AKAリンクフェーズでは、コンパイラは、すべてのディレクティブを探し、すべて作成します$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
$ scope.nameの変化を見ていたが、変更されたことを報告し、それが別の強制します$digest
ループを。$digest
ループを実行することです。つまり、入力に文字を書き込むたびに、ループは$watch
このページのすべてをチェックして実行されます。$apply
イベントが発生したときに呼び出すと、角度のコンテキストを通過しますが、呼び出さない場合は、イベントの外側で実行されます。それはそれと同じくらい簡単です。$apply
呼び出します$digest()
ループを内部的にすべての監視を反復処理して、DOMが新しく更新された値で更新されるようにします。
$apply()
この方法は、全体にウォッチャをトリガする$scope
のに対し、チェーン$digest()
方式のみ電流にウォッチャをトリガする$scope
とchildren
。上位の$scope
オブジェクトがローカルの変更について知る必要がない場合は、を使用できます$digest()
。
私はカバー非常に綿密な動画を見つけ$watch
、$apply
、$digest
とにサイクルをダイジェスト:
AngularJS-Watcher、$ watch、$ watchGroup、$ watchCollection、ng-changeを理解する
AngularJS-ダイジェストサイクルの理解(ダイジェストフェーズまたはダイジェストプロセスまたはダイジェストループ)
以下は、概念を説明するためにこれらのビデオで使用されている2つのスライドです(上記のリンクが削除されている/機能していない場合に備えて)。
上の画像では、「$ scope.c」はどのデータバインディング(マークアップ)でも使用されていないため、監視されていません。他の2つ($scope.a
および$scope.b
)が監視されます。
上記の画像から:それぞれのブラウザーイベントに基づいて、AngularJSはイベントをキャプチャし、ダイジェストサイクルを実行し(変更のすべての監視を通過します)、監視機能を実行し、DOMを更新します。ブラウザイベントでない場合は、$apply
またはを使用して、ダイジェストサイクルを手動でトリガーできます$digest
。
詳細$apply
と$digest
:
ある$watchGroup
と$watchCollection
同様。具体的に$watchGroup
は、DOMオブジェクトではないビューに複数のプロパティを持つオブジェクトを更新する関数を呼び出す場合に非常に役立ちます。たとえば、キャンバス、WebGL、サーバーリクエストの別のビューなどです。
ここでは、ドキュメントのリンク。
$watchCollection
あなたがすでにそうしたのを私は見ます。 これは、AngularJSサイトからのドキュメントです。彼らは$watch
深さの非常に素晴らしい視覚を提供します。情報がページの下部に近いことに注意してください。
退屈で眠そうな上記すべてを読み終えてください(申し訳ありませんが、本当です)。非常に技術的で、詳細で、詳細で、ドライ。なぜ私は書いているのですか?AngularJSは巨大であるため、相互に関連する多くの概念が、誰でも気が狂う可能性があります。私はしばしば自分自身に尋ねました、私はそれらを理解するのに十分賢くないですか?番号!技術を説明することができる人がほとんどいないためですすべての用語です!わかりました、試してみましょう:
1)それらはすべてイベント駆動型のものです。(笑い声は聞こえますが、読み進めてください)
イベントドリブンが何であるかわからない場合は、ページにボタンを配置すると思います。「オンクリック」を使用して、ボタンを関数と接続し、ユーザーがクリックして、内部に埋め込んだアクションをトリガーするのを待ちます。関数。または、SQL Server / Oracleの「トリガー」を考えてみてください。
2)$ watchは「オンクリック」です。
特別なのは、2つの関数をパラメーターとして取ることです。1つはイベントからの値を与え、2つ目は値を考慮に入れます...
3)$ digestは精力的にチェックするボスです。
4)$ applyは、フェイルプルーフのように、手動で実行する方法を提供します(オンクリックで起動しない場合は、強制的に実行します)。
それでは、視覚化してみましょう。これを想像して、アイデアをつかみやすくします。
レストランの中、
-ウェイター
顧客からの注文を受けることになっていますが、これは
$watch(
function(){return orders;},
function(){Kitchen make it;}
);
-すべてのウェイターが起きていることを確認するために走り回っているマネージャー。顧客からの変更の兆候に対応します。これは$digest()
-OWNERは、要求に応じて全員を駆り立てる究極の力を持っています。これは$apply()