382

Watchersとの両方が、AngularJS でObservers何かが変更されるとすぐに計算されることを私は知っています。$scopeしかし、両者の違いを正確に理解できませんでした。

私の最初の理解は、関数が実行されたときに実行されるObserversHTML側の条件である角度式に対して計算されるということです。私はちゃんと考えていますか?Watchers$scope.$watch()

4

4 に答える 4

613

$observe()Attributesオブジェクトのメソッドであるため、DOM 属性の値の変化を監視/監視するためにのみ使用できます。ディレクティブ内でのみ使用/呼び出されます。補間を含む DOM 属性 ({{}} など) を観察/監視する必要がある場合は、$observe を使用します。
たとえば、attr1="Name: {{name}}"、次にディレクティブで:attrs.$observe('attr1', ...)
(試しscope.$watch(attrs.attr1, ...)てみても、{{}} のために機能しません -- が得られますundefined。) 他のすべてには $watch を使用します。

$watch()はもっと複雑です。関数または文字列のいずれかである「式」を観察/監視できます。式が文字列の場合、関数に$parseされます (つまり、 Angular 式として評価されます)。(すべてのダイジェスト サイクルで呼び出されるのはこの関数です。) 文字列式に {{}} を含めることはできません。$watch はScopeオブジェクトのメソッドであるため、スコープ オブジェクトにアクセスできる場所ならどこでも使用/呼び出すことができます。

  • コントローラー -- 任意のコントローラー -- 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')てみると、 string が得られますがmyModel.some_prop、これはおそらくあなたが望むものではありません。)

@PrimosK の回答に関するコメントで説明されているように、すべての $observes と $watches はダイジェスト サイクルごとにチェックされます。

分離スコープを持つディレクティブはより複雑です。'@' 構​​文が使用されている場合、補間 ({{}} など) を含む DOM 属性を$observeまたは $watchできます。($watch で機能する理由は、'@' 構​​文が補間を行うためです。したがって、$watch は {{}} のない文字列を認識します)。この場合も $observe します。

これらすべてをテストするために、2 つのディレクティブを定義するPlunkerを作成しました。一方 ( 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 の違いを確認してください。次に、リンクをクリックして、クリック ハンドラーによって行われたプロパティの変更によってトリガーされる $observes と $watches を確認します。

リンク関数が実行されるとき、{{}} を含む属性はまだ評価されないことに注意してください (そのため、属性を調べようとすると、 が返されますundefined)。補間された値を表示する唯一の方法は、$observe を使用することです (または、'@' で分離スコープを使用する場合は $watch)。したがって、これらの属性の値の取得は非同期操作です。(これが $observe 関数と $watch 関数が必要な理由です。)

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

$watch 式に関するVojta の Google グループ投稿も参照してください。

于 2013-02-16T06:54:22.357 に答える
26

私があなたの質問を正しく理解しているなら、あなたはリスナーのコールバックをに登録する$watchか、それをで行うかどうかの違いは何であるかを尋ねています$observe

に登録されたコールバックは、実行$watch時に発生し$digestます。

に登録されたコールバック$observeは、補間を含む属性の値が変更されたときに呼び出されます(例attr="{{notJetInterpolated}}")。


ディレクティブ内では、非常によく似た方法で両方を使用できます。

    attrs.$observe('attrYouWatch', function() {
         // body
    });

また

    scope.$watch(attrs['attrYouWatch'], function() {
         // body
    });
于 2013-02-14T14:23:19.073 に答える