アングラルJSの$apply()方法
7291 ワード
この数日間、buddyの指定した任務によって、アグラJSのものを共有します.先端で純粋な新米に属している私にとって、Javascriptはまだ一知半解で、直接にangglar JSを上手にしたいです.でも、工夫さえすれば、反人類のデザインでも大きな問題ではないと信じています. Okay、余計なことを言わない.アングラーJSとは何かを知るために、まずScopeから始めます.Scopeとは何ですか?公式文書の一節を借りる:
「scope」 is an object that refers to the appration model.It is an exection context for expressions.Scoopes arranged in hierarchical structure whimic the DOM structure of the ap plication.Scompes can watch expressions and propagate events.」
見終わった後、他のプログラミング言語に類比して、ScopeはData Modelのスコープのように、Expressionsの実行に文脈を提供していると感じます.とりあえず、このように理解してください.
Scopeの特性 次に、Scopeの特性を見てみましょう. Scopeは、Modelの変化を監視するためのウォッチ方法を提供します. Scopeは、Modelの変化を伝えるためにapply方法を提供する. Scopeは、異なるappication componentsと属性アクセス権限を分離するために引き継がれます. Scopeは、Expressitionsの計算にコンテキストを提供する. この4つの特性については、アクションScript、C+++、Javaを勉強したことがありますので、第一、第三、第四は分かりにくくないです.土鍋破りの原則で、グーグルを通じていくつかのものを見つけました.経験のあるベテランには、レンガを軽く撮ってください.
ソースJavascript まず、一見して、$scope.$apply()は、bindingsを更新する一般的な方法のようです.ちょっと考えてみますが、なぜ私たちはそれが必要ですか?普通はいつ使いますか?この二つの問題をはっきりさせるには、Javascriptから話さなければなりません.Javascriptコードでは、コードの断片が実行される順番になると、ブラウザは現在のセグメントだけを実行します.他のことは何もしません.だから時にはいくつかするのがあまり良くないホームページ、あるものをクリックした後で押さえて居住することができて、Javascriptの仕事の方式はこの現象の原因の1つを招くことができます!次のコードで感じてみます.
どうやってbindings を更新しますか?
じゃ、関係ないような話をしてから、本題に戻ります.angglar JSはいつデータの変化とページの更新が必要かどうやって分かりますか?コードはいつデータが修正されたかを知る必要がありますが、あるオブジェクトのデータが変わったと直接に通知する方法がありません.(ECMAScript 5はこの問題を解決しようとしていますが、まだ実験段階です.)現在主流の戦略は以下の二つの解決案があります.一つは特殊なオブジェクトを使う必要があります.すべてのデータは直接にpropertyで指定するのではなく、オブジェクトを呼び出す方法で設定するしかないです.このようにすれば、すべての修正が記録されます.いつページが更新されるかが分かります.このようにする弊害は私達が必ず特殊な対象を継承しなければなりません.賦課については、object.set('key'、'value')ではなく、object.key=valueでしかない.フレームの中では、エバーJSとKnockout JSのようにしています.もう一つは、angglar JSが採用した方式で、Javascriptコードの実行が終了するたびに、データの変更があるかどうかをチェックします.これは効率的ではないように見えます.性能に深刻な影響を与えます.しかし、angglar JSはいくつかの比較的巧妙な手段を使ってこの問題を解決しました.このようにするメリットは、任意の対象を自由に使ってもいいし、割当方法にも制限がないし、データの変化にも気づくことができるということです. angglar JSのこのような解決策に対して、私達が関心を持っているのはいつデータが変化したのかということです.これもまさに$scope.$apply()が役に立つところです.結合されたデータが変化しているかどうかを確認するためには、実際には$scope.$digest()によって行われますが、私たちはこの方法を直接呼び出したことはほとんどありません.scope.$appley()メソッドは関数または表現を持って、それを実行して、最後に$scope.$digest()メソッドを呼び出してbindingsまたはwatchersを更新します.
はいつ使いますか?
それともその問題ですか?私たちは一体いつまでにアプリを呼び出す必要がありますか?状況は非常に少ないです.実際にはほとんどのコードは全部$scope.$apple()の中に含まれています.ng-click、controllerの初期化、httpのコールバック関数などです.これらの場合、私達は自分で呼び出す必要はありません.実際には私達も自分で呼び出すことができません.そうでなければ、$apply()メソッドの中で呼び出してください.新しい実行シーケンスでコードを実行する必要があるなら、それを使用する必要があります.そして、この新しい実行シーケンスがanglar JSのライブラリの方法によって作成されたのではなく、このときにコードを$scope.$appy()で包む必要があります.次は一例で説明します.[HTML]
科学は両刃の剣を です.
最後に、私たちはもう一つの方法を見に来ましょう.angglar JSは私たちのために多くのことをしてくれましたが、私たちもそのために機会をなくしました.下記の疑似コードから見れば分かります.
まとめてみます. $apply()メソッドは、例えば、DOMイベント、setTimeout、XHR、または他の第三者のライブラリなどのアングラーJSの表現をアングラーフレーム以外で実行することができる.これはただの始まりです.水はまだ深いので、みんなでdeep diveに来てください.================================================================================================================== Reference 原文:http://jimhoskins.com/2012/12/17/angularjs-and-apply.html
【余談】 If you arassigning a string containing a.char,you will need to use the$appy(fn)method or you will get an error.Example:
「scope」 is an object that refers to the appration model.It is an exection context for expressions.Scoopes arranged in hierarchical structure whimic the DOM structure of the ap plication.Scompes can watch expressions and propagate events.」
見終わった後、他のプログラミング言語に類比して、ScopeはData Modelのスコープのように、Expressionsの実行に文脈を提供していると感じます.とりあえず、このように理解してください.
var button = document.getElementById('clickMe');
function buttonClicked () {
alert('the button was clicked');
}
button.addEventListener('click', buttonClicked);
function timerComplete () {
alert('timer complete');
}
setTimeout(timerComplete, 5000);
Javascriptコードをロードする時、まずIDを探して「clickMe」というボタンを押してからモニターを追加して、タイムアウトを設定します.5秒待ってください.ダイアログが出ます.ページを更新してすぐにclickMeボタンをクリックすると、ダイアログが表示されます.OKをクリックしないと、timerCoplete関数はいつまでも実行する機会がありません.じゃ、関係ないような話をしてから、本題に戻ります.angglar JSはいつデータの変化とページの更新が必要かどうやって分かりますか?コードはいつデータが修正されたかを知る必要がありますが、あるオブジェクトのデータが変わったと直接に通知する方法がありません.(ECMAScript 5はこの問題を解決しようとしていますが、まだ実験段階です.)現在主流の戦略は以下の二つの解決案があります.一つは特殊なオブジェクトを使う必要があります.すべてのデータは直接にpropertyで指定するのではなく、オブジェクトを呼び出す方法で設定するしかないです.このようにすれば、すべての修正が記録されます.いつページが更新されるかが分かります.このようにする弊害は私達が必ず特殊な対象を継承しなければなりません.賦課については、object.set('key'、'value')ではなく、object.key=valueでしかない.フレームの中では、エバーJSとKnockout JSのようにしています.もう一つは、angglar JSが採用した方式で、Javascriptコードの実行が終了するたびに、データの変更があるかどうかをチェックします.これは効率的ではないように見えます.性能に深刻な影響を与えます.しかし、angglar JSはいくつかの比較的巧妙な手段を使ってこの問題を解決しました.このようにするメリットは、任意の対象を自由に使ってもいいし、割当方法にも制限がないし、データの変化にも気づくことができるということです. angglar JSのこのような解決策に対して、私達が関心を持っているのはいつデータが変化したのかということです.これもまさに$scope.$apply()が役に立つところです.結合されたデータが変化しているかどうかを確認するためには、実際には$scope.$digest()によって行われますが、私たちはこの方法を直接呼び出したことはほとんどありません.scope.$appley()メソッドは関数または表現を持って、それを実行して、最後に$scope.$digest()メソッドを呼び出してbindingsまたはwatchersを更新します.
それともその問題ですか?私たちは一体いつまでにアプリを呼び出す必要がありますか?状況は非常に少ないです.実際にはほとんどのコードは全部$scope.$apple()の中に含まれています.ng-click、controllerの初期化、httpのコールバック関数などです.これらの場合、私達は自分で呼び出す必要はありません.実際には私達も自分で呼び出すことができません.そうでなければ、$apply()メソッドの中で呼び出してください.新しい実行シーケンスでコードを実行する必要があるなら、それを使用する必要があります.そして、この新しい実行シーケンスがanglar JSのライブラリの方法によって作成されたのではなく、このときにコードを$scope.$appy()で包む必要があります.次は一例で説明します.[HTML]
<div ng:app ng-controller="Ctrl">{{message}}</div>
[Javascript]functionCtrl($scope) {
$scope.message ="Waiting 2000ms for update";
setTimeout(function () {
$scope.message ="Timeout called!";
// AngularJS unaware of update to $scope
}, 2000);
}
上のコードは実行後のページに表示されます.Waiting 2000 ms for udate.明らかにデータの更新はアングラーJSに気付かれていない. 続いて、Javascriptのコードを少し修正して、$scope.$アプリで包みます.[Javascript]functionCtrl($scope) {
$scope.message ="Waiting 2000ms for update";
setTimeout(function () {
$scope.$apply(function () {
$scope.message ="Timeout called!";
});
}, 2000);
}
今回は以前と違って、ページ上でまずWaiting 2000 ms for udateが表示されます.2秒後に内容がTimeout caledに変更されます. .明らかにデータの更新はangglar JSによって発見されました. NOTE:私たちはこのようにするべきではないです.anglar JSが提供する$timeout方法を使って、自動的に$apply方法で包装されます.最後に、私たちはもう一つの方法を見に来ましょう.angglar JSは私たちのために多くのことをしてくれましたが、私たちもそのために機会をなくしました.下記の疑似コードから見れば分かります.
function$apply(expr) {
try {
return$eval(expr);
} catch(e) {
$exceptionHandler(e);
} finally {
$root.$digest();
}
}
すべての異常は捕獲されます.また投げられません.最後には$digest()メソッドを呼び出します.var imagename = "myimage.png";
$scope.$apply($scope.image = imagename);
The code above will throw an error because Anglar will interpret the string as an object.Using the function method is does happen.Example:$scope.$apply(function () {
$scope.image = imagename;
});