Watchers
との両方が、AngularJS でObservers
何かが変更されるとすぐに計算されることを私は知っています。$scope
しかし、両者の違いを正確に理解できませんでした。
私の最初の理解は、関数が実行されたときに実行されるObservers
HTML側の条件である角度式に対して計算されるということです。私はちゃんと考えていますか?Watchers
$scope.$watch()
Watchers
との両方が、AngularJS でObservers
何かが変更されるとすぐに計算されることを私は知っています。$scope
しかし、両者の違いを正確に理解できませんでした。
私の最初の理解は、関数が実行されたときに実行されるObservers
HTML側の条件である角度式に対して計算されるということです。私はちゃんと考えていますか?Watchers
$scope.$watch()
$observe()はAttributesオブジェクトのメソッドであるため、DOM 属性の値の変化を監視/監視するためにのみ使用できます。ディレクティブ内でのみ使用/呼び出されます。補間を含む DOM 属性 ({{}} など) を観察/監視する必要がある場合は、$observe を使用します。
たとえば、attr1="Name: {{name}}"
、次にディレクティブで:attrs.$observe('attr1', ...)
。
(試しscope.$watch(attrs.attr1, ...)
てみても、{{}} のために機能しません -- が得られますundefined
。) 他のすべてには $watch を使用します。
$watch()はもっと複雑です。関数または文字列のいずれかである「式」を観察/監視できます。式が文字列の場合、関数に$parseされます (つまり、 Angular 式として評価されます)。(すべてのダイジェスト サイクルで呼び出されるのはこの関数です。) 文字列式に {{}} を含めることはできません。$watch はScopeオブジェクトのメソッドであるため、スコープ オブジェクトにアクセスできる場所ならどこでも使用/呼び出すことができます。
文字列は 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 グループ投稿も参照してください。
私があなたの質問を正しく理解しているなら、あなたはリスナーのコールバックをに登録する$watch
か、それをで行うかどうかの違いは何であるかを尋ねています$observe
。
に登録されたコールバックは、実行$watch
時に発生し$digest
ます。
に登録されたコールバック$observe
は、補間を含む属性の値が変更されたときに呼び出されます(例attr="{{notJetInterpolated}}"
)。
ディレクティブ内では、非常によく似た方法で両方を使用できます。
attrs.$observe('attrYouWatch', function() {
// body
});
また
scope.$watch(attrs['attrYouWatch'], function() {
// body
});