AngularJS で $scope.$watch と $scope.$apply を使用するにはどうすればいいですか? 質問する

AngularJS で $scope.$watch と $scope.$apply を使用するにはどうすればいいですか? 質問する

$scope.$watchと の使い方がわかりません$scope.$apply。公式ドキュメントは役に立ちません。

具体的に理解できない点:

  • それらはDOMに接続されていますか?
  • モデルの DOM 変更を更新するにはどうすればよいですか?
  • それらの間の接続点は何ですか?

私は試したこのチュートリアル$watch、しかし、との理解が$apply当然のこととみなされます。

何をすべき$apply$watch、またそれらをどのように適切に使用すればよいか?

ベストアンサー1

AngularJS を理解するには、その仕組みを知っておく必要があります。

ダイジェストサイクルと$scope

まず第一に、AngularJS はいわゆるダイジェスト サイクルの概念を定義します。このサイクルはループと見なすことができ、その間に AngularJS はすべての によって監視されている$scopeすべての変数に変更があるかどうかを確認します。したがって、$scope.myVarコントローラーで を定義し、この変数が監視対象としてマークされてmyVarいる場合、ループの各反復での変更を監視するように AngularJS に暗黙的に指示していることになります。

当然、次のような疑問が湧いてきます。すべてが$scope監視対象になっているのでしょうか? 幸いなことに、そうではありません。 内のすべてのオブジェクトの変更を監視すると$scope、ダイジェスト ループの評価に非常に長い時間がかかり、パフォーマンスの問題にすぐに直面することになります。そのため、AngularJS チームは、変数を$scope監視対象として宣言する 2 つの方法を提供しました (以下を参照)。

$watchは$scopeの変更を監視するのに役立ちます

$scope変数を監視対象として宣言する方法は 2 つあります。

  1. テンプレート内で式を使用して<span>{{myVar}}</span>
  2. $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は変更をダイジェストサイクルに統合することを可能にします

$applyこの関数は統合メカニズムとして考えることができます。オブジェクトに直接アタッチされた監視対象の変数$scopeを変更するたびに、AngularJS は変更が発生したことを認識します。これは、AngularJS がそれらの変更を監視することをすでに認識しているためです。したがって、フレームワークによって管理されるコードで変更が発生した場合、ダイジェスト サイクルが続行されます。

ただし、AngularJS の世界外で何らかの値を変更し、その変更が正常に伝播することを確認したい場合があります。次のことを考えてみてください。jQuery$scope.myVarのハンドラー内で変更される値があります$.ajax()。これは将来のある時点で発生します。AngularJS は jQuery を待機するように指示されていないため、これが発生するのを待つことができません。

これに対処するために、$applyが導入されました。これにより、消化サイクルを明示的に開始できます。ただし、これは一部のデータを AngularJS に移行する場合にのみ使用してください (他のフレームワークとの統合)。このメソッドを通常の AngularJS コードと組み合わせて使用​​しないでください。その場合、AngularJS はエラーをスローします。

これらすべては DOM とどのように関係しているのでしょうか?

さて、これですべて理解できたので、もう一度チュートリアルに従う必要があります。ダイジェスト サイクルは、$scope何も変更されない限り、すべての にアタッチされているすべてのウォッチャーを評価することで、UI と JavaScript コードが同期された状態を維持できるようにします。ダイジェスト ループでそれ以上変更が行われない場合は、終了したと見なされます。

$scopeオブジェクトは、コントローラー内で明示的に、または{{expression}}ビュー内のフォームで直接宣言することによって、オブジェクトにアタッチできます。

さらに詳しい情報:

おすすめ記事