私は両方のことを知っているWatchers
とはObservers
で何かするとすぐに計算され$scope
AngularJSの変化。しかし、両者の違いは正確には理解できませんでした。
私の最初の理解は、関数が実行されたときに実行されるObservers
HTML側の条件である角度式に対して計算Watchers
される$scope.$watch()
ことです。私はきちんと考えていますか?
私は両方のことを知っているWatchers
とはObservers
で何かするとすぐに計算され$scope
AngularJSの変化。しかし、両者の違いは正確には理解できませんでした。
私の最初の理解は、関数が実行されたときに実行されるObservers
HTML側の条件である角度式に対して計算Watchers
される$scope.$watch()
ことです。私はきちんと考えていますか?
回答:
$ observe()は、 Attributesオブジェクトのメソッドであるため、DOM属性の値の変化を観察または監視するためにのみ使用できます。内部ディレクティブでのみ使用/呼び出されます。補間を含むDOM属性(つまり、{{}})を観察または監視する必要がある場合は、$ observeを使用します。
例えば、attr1="Name: {{name}}"
は、ディレクティブで:attrs.$observe('attr1', ...)
。
(scope.$watch(attrs.attr1, ...)
{{}}のために試しても機能しません-が表示されますundefined
。)それ以外の場合は、$ watchを使用します。
$ watch()はより複雑です。「式」を観察/監視できます。式は、関数または文字列のいずれかです。式が文字列の場合、それは関数に $ parse 'd(つまり、 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')
、文字列が表示されますがmyModel.some_prop
、これはおそらく望んでいるものではありません。)
@PrimosKの回答のコメントで説明されているように、すべての$ observesと$ watchesはダイジェストサイクルごとにチェックされます。
分離スコープを持つディレクティブは、より複雑です。'@'構文を使用する場合、補間を含むDOM属性(つまり、{{}})を$ observe または$ watchできます。($ watchで機能するのは、 '@'構文が補間を実行するためです。したがって、$ watchは{{}}のない文字列を参照します。)いつ使用するかを覚えやすくするために、この場合も$ observeします。
これをすべてテストするために、2つのディレクティブを定義するPlunkerを作成しました。1つ(d1
)は新しいスコープを作成せず、もう1つ()はd2
分離スコープを作成します。各ディレクティブには同じ6つの属性があります。各属性は、$ observe'dと$ watch'dの両方です。
<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グループの投稿も参照してください。
ng-src/ng-href
使用attr.$observe
するのか考えていscope.$watch
ますか?
@
構文を使用するときにそれらは交換可能です。パフォーマンスの違いはないと思います(ただし、実際のソースコードは確認していません)。
私はあなたの質問を理解していれば右に、あなたがして、リスナーのコールバックを登録した場合の違いは何であるか求めている$watch
か、あなたがそれを行う場合$observe
。
に登録されたコールバックは、実行$watch
時に発生し$digest
ます。
に登録されて$observe
いるコールバックは、補間を含む属性の値が変更されたときに呼び出されます(などattr="{{notJetInterpolated}}"
)。
ディレクティブ内では、非常によく似た方法で両方を使用できます。
attrs.$observe('attrYouWatch', function() {
// body
});
または
scope.$watch(attrs['attrYouWatch'], function() {
// body
});
$digest
フェーズで反映されるため、$observe
コールバックがで呼び出されると想定しても安全$digest
です。そして、$watch
コールバックも呼び出されます$digest
が、値が変更されるたびに呼び出されます。彼らはまったく同じ仕事をしていると思います:「式を見て、コールバックに値の変更を呼び出します」。キーワードの違いはおそらく、開発者を混乱させないための単なる構文上の砂糖です。
これはかなり明白だと思います:
覚えておいてください:両方の関数には2つの引数があります、
$observe/$watch(value : string, callback : function);
function (oldValue, newValue)
を作成しましたplunkerので、実際に両方の利用状況を把握できます。わかりやすくするために、カメレオンのアナロジーを使用しました。
$ observeが$ watchと異なるのはなぜですか?
watchExpressionが評価され、各digest()サイクルで前の値と比較されます。watchExpression値に変更がある場合、watch関数が呼び出されます。
$ observeは、補間された値の監視に固有です。ディレクティブの属性値が補間されている場合、たとえばdir-attr="{{ scopeVar }}"
、補間された値が設定されている場合(したがって、$ digestがすでに更新を行う必要があると判断した場合)に、observe関数が呼び出されます。基本的に、すでに補間のウォッチャーがあり、$ observe関数はそれを便乗させます。
compile.jsの $ observe&$ setを参照してください