1. ホーム
  2. ジャバスクリプト

[解決済み】AngularJS 。observe メソッドと $watch メソッドの違い

2022-03-24 17:30:48

質問

私は、両方の WatchersObservers の中に何かあるとすぐに計算されます。 $scope は、AngularJSで変更されます。しかし、この2つの違いは一体何なのか、理解できませんでした。

私の最初の理解では Observers は、HTML 側の条件である angular 式に対して計算されます。 Watchers が実行されたとき $scope.$watch() 関数が実行されます。私の考えは正しいでしょうか?

どのように解決するのですか?

観察() 属性 そのため、DOM 属性の値の変化を観察するためにのみ使用することができます。 これは、ディレクティブの内部でのみ使用/呼び出しが可能です。 補間を含む DOM 属性(すなわち、{{}}のもの)を監視/観察する必要がある場合は、$observe を使用してください。

attr1="Name: {{name}}" とすると、ディレクティブの中で attrs.$observe('attr1', ...) .

(もし、あなたが scope.$watch(attrs.attr1, ...) があるためうまくいきません。 undefined .) それ以外のものは$watchを使用します。

$watch() はもっと複雑です。 ここで、式は関数でも文字列でもかまいません。 式が文字列の場合、それは パース 'd(つまり、評価されるのは Angular式 を関数に変換します。 (ダイジェストサイクルごとに呼び出されるのはこの関数です。) 文字列式に {{}} を含めることはできません。 watchは スコープ そのため、スコープオブジェクトにアクセスできる場所であればどこでも使用/呼び出しが可能です。

  • コントローラ -- ng-view、ng-controller、またはディレクティブコントローラによって作成された任意のコントローラです。
  • ディレクティブのリンク関数、これはスコープにもアクセスできるため

文字列はAngularの式として評価されるため、モデルやスコープのプロパティを観察/監視したい場合は$watchがよく使われます。 例 attr1="myModel.some_prop" で、コントローラやリンク関数の中で scope.$watch('myModel.some_prop', ...) または scope.$watch(attrs.attr1, ...) (または scope.$watch(attrs['attr1'], ...) ).

(もし、あなたが attrs.$observe('attr1') という文字列が表示されます。 myModel.some_prop これはおそらく、あなたが望むものではありません)。

PrimosK さんの回答へのコメントにもあるように、すべての $observes と $watches は ダイジェストサイクル .

スコープを分離したディレクティブはより複雑です。 もし '@' 構文が使われていれば、 $observe または $watch を含むDOM属性(つまり、{{}}のもの)。 ($watch と共に動作するのは、'@' 構文が以下の処理を行うからです。 補間 のない文字列が表示されます)。 どちらを使うか覚えやすいように、この場合にも $observe を使うことをお勧めします。

これらのことをテストするために、私は プランカー という2つのディレクティブを定義しています。 ひとつは ( d1 ) は新しいスコープを作成せず、もう一方 ( d2 ) は分離されたスコープを作成します。 各ディレクティブは同じ6つの属性を持っています。 各属性は、$observe'dと$watch'edの両方があります。

<div d1 attr1="{{prop1}}-test" attr2="prop2" attr3="33" attr4="'a_string'"
        attr5="a_string" attr6="{{1+aNumber}}"></div>

コンソールログを見て、リンク関数の$observeと$watchの違いを確認しましょう。 そして、リンクをクリックし、クリックハンドラによって行われたプロパティの変更によって、どの$observeと$watchがトリガーされたかを見てください。

リンク関数が実行されるとき、{{}}を含む属性はまだ評価されていないことに注意してください(したがって、属性を調べようとすると、次のようになります)。 undefined ). 補間された値を見るには、$observe (あるいは '@' のついた孤立したスコープを使う場合は $watch) を使うしかありません。 したがって、これらの属性の値を取得するのは 非同期 操作になります。 (そして、これが$observeと$watch関数が必要な理由です)。

時には、$observeや$watchが不要な場合もあります。 例えば、属性に数値やブーリアン(文字列ではない)が含まれている場合、一度だけ評価すればよい。 attr1="22" そして、例えば、リンク関数で。 var count = scope.$eval(attrs.attr1) . もしそれが単なる定数文字列であれば - attr1="my string" - を使用すればよい。 attrs.attr1 をディレクティブに追加します ($eval() は必要ありません)。

以下もご参照ください。 Vojtaのgoogleグループ投稿 については、$watch 式を使用しています。