1。スコープとは何ですか?
scope(http://code.angularjs.org/1.0.2/docs/api/ng.$rootscope.scope)は、アプリケーションモデルを指すオブジェクトです。また、式の実行コンテキスト(http://www.cnblogs.com/lclao/archive/2012/09/16/2687162.html)です。スコープは、アプリケーションと同様のDOM構造の階層に配置されます。スコープは、表現と伝播イベントを監視(監視、$監視)できます。
2。範囲の特性
3.データモデルとしてのスコープ(データモデルとしてのスコープ)
スコープは、アプリケーションコントローラーとビューの間のリンクです。テンプレートリンクの段階(http://www.cnblogs.com/lclao/archive/2012/09/04/2669802.html)、指令(http://www.cnblogs.com/lclao/archive/2012/09/09/09/267190スコープ。 $ watchでは、ディレクティブが属性の変更を知ることができるため、ディレクティブは更新された値をDOMにレンダリングします。
コントローラーと指令の両方が範囲に言及していますが、互いに参照されません。この配置は、コントローラーをディレクティブとDOMから分離します。これは、コントローラーをビューから分離し、アプリケーションのテストストーリーを大幅に改善するため、重要な場所です。
<!doctype html> <html lang = "zh-cn" ng-app> <head> <meta charset = "utf-8"> <title> data-model </title> <style type = "text/css"> .ng-cloak {display:none; none; } </style> </head> <body> <div ng-controller = "mycontroller"> your name:<input type = "text" ng-model = "username"/> <button ng-click = "sayhello()" type = "text/javascript"> </script> <script type = "text/javascript"> function mycontroller($ scope){$ scope.username = "my little dada"; $ scope.sayhello = function(){$ scope.greeting = "hello〜" + $ scope.username + "!"; }; } </script> </body> </html>上記の例では、MyControllerが「My Little Dada」に範囲でユーザー名属性を割り当てていることに気付くことができます。次に、scopeは割り当ての入力を通知し、ユーザー名を入力に事前に充填します。これは、コントローラーがどのようにデータをスコープに書き込むことができるかを示しています。
同様に、コントローラーは、ユーザーが「ウェルカム」ボタンをクリックしたときにトリガーされるSayhelloメソッドのように、動作をスコープに添付できます。 Sayhelloメソッドは、ユーザー名属性を読み取るか、グリーティング属性を作成できます。これは、HTML入力コントロールにバインドされている場合、スコープのプロパティが自動的に更新されることを示しています。
論理的には、{{Greeting}}を表示するには、次の2つのポイントが含まれます。
{{{Greeting}}式を定義するテンプレートDOMノードでスコープを検索します。この例では、このスコープはMyControllerに渡されたスコープと同じです。 (後でスコープ階層について説明します)
グリーティング式は、以前に取得されたスコープを通じて評価され、結果はDOM要素を囲むテキストの値として使用されます。
スコープと独自のプロパティは、ビューをレンダリングするためのデータとして使用できると考えることができます。スコープは、関連するすべてのものに対する単一の真実の源です。
テスト可能性の観点からは、詳細の干渉なしにテスト動作に(焦点を合わせる)ことができるため、コントローラーとビューの分離は喜んでいます。
it( 'hello'、hello '、function(){var scopemock = {}; var cntl = new mycontroller(scopemock); // usernameが事前に満たされていることを主張します(scopemock.username).toequal(' world ');想像(scopemock.greeting).toequal( 'hello angular!');});4。スコープ階層(スコープ階層)
各Angularアプリケーションには、1つのルートスコープのみがありますが、複数の子スコープを持つことができます。
いくつかの指令が新しい子スコープを作成するため、アプリケーションには複数の子スコープを持つことができます(NG-Reepeatなどの新しいスコープを作成できるディレクティブを確認するためのディレクティブドキュメントを参照してください)。新しいスコープが作成されると、子スコープとして親スコープに追加されます。このようにして、それらが取り付けられているDOMに似たツリー構造が作成されます。
Angularが{{{username}}を評価すると、最初に現在の要素に関連付けられたスコープのユーザー名プロパティを調べます。対応するプロパティが見つからない場合、ルートスコープに達するまで親の範囲を上方に検索します。 JavaScriptでは、この動作は「プロトタイプ継承」と呼ばれ、子の範囲は通常、親から継承されます。
この例は、アプリケーション内のプロパティの範囲(それは何ですか)とプロトタイプの継承を示しています。
<!doctype html> <html lang = "zh-cn" ng-app> <head> <meta charset = "utf-8"> <title> scope-hierarchies </title> <style type = "text/css"> .ng-cloak {display:none:none; } .ng-scope {border:1px dashed red; } </style> </head> <body> <div ng-controller = "mycontroller"> manager:{{employee.name}} [{department}}] <br/>レポート:<ul> <li ng-repeat = "従業員の従業員の従業員。 <hr/> {{greeding}} </div> <script src = "../ angular-1.0.1.js" type = "text/javascript"> </script> <script> <script = "text/javascript"> function myController($ scope){$ scope.department = " $ scope.employee = {name: "my little dada"、レポート:[{name: "lclao"}、{name: "who^o^"}]}; } </script> </body> </html>Angularは、Ng-Scopeクラスをスコープに付着する要素に自動的に配置することに注意してください。 <style>は上記の例で定義されており、赤い点線を通る新しいスコープの範囲を強調しています。リピーターは{{employee.name}}式を評価するため、子の範囲が必要ですが、式が評価される範囲に応じて、異なるスコープには異なる結果があります。同様に、{{department}}の値は、ルートスコープのプロトタイプから継承されます。それがある場合にのみ、部門の属性を定義できます。
5。DOMからスコープを取得する(DOMからスコープを取得)
スコープは$ Scope Data属性としてDOMに添付されており、デバッグ目的で検索に使用できます。 (アプリケーションでこの方法でスコープを取得することは不可能です。)DOMに接続されたルートスコープの位置は、NG-APP指令の位置によって定義されます。通常、ng-appは<html>要素に配置されますが、他の要素に配置することもできます。たとえば、角度によって制御する必要があるビューの一部のみが必要です。
デバッガーの範囲を表示:
1.ブラウザで、興味のある要素を右クリックして、[要素を表示]を選択します。ブラウザデバッガーが選択した要素を強調していることがわかります。
2。デバッガーを使用すると、コンソール内の$ 0変数を介して現在選択されている要素にアクセスできます。
3.関連する範囲を表示する場合は、コンソールにAngular.Element($ 0).Scope()を入力できます。
6.スコープイベントの伝播(スコープイベントの伝播)
スコープは、DOMイベントと同様の方法でイベントを伝播できます。イベントは放送できます(http://code.angularjs.org/1.0.2/docs/api/ng.$Rootscope.Scope#YOTBROADCASS) (現在のスコープが聴くと、実行されます)
<!doctype html> <html lang = "zh-cn" ng-app> <head> <meta charset = "utf-8"> <title> scope-event-propagation </title> <style type = "text/css"> .ng-cloak {display:none:none; } </style> </head> <body> <div ng-controller = "myController"> root Scope count:{{count}}} <ul> <li ng-repeat = "i in [1]" ng-controller = "mycontroller"> <button ng-click = "$ emit( 'myevent') ng-click = "$ broadcast( 'myevent')"> $ broadcast( "myevent")</button> <br/>ミドルスコープカウント:{{count}}} <ul> <li ng-repeat = "item in [1,2]" ng-controller = "mycontroller"> leaf count:{{count} </li> </ul> </div> <script src = "../ angular-1.0.1.js" type = "text/javascript"> </script> <script = "text/javascript"> function mycontroller($ scope){$ scope.count = 0; $ scope。$ on( "myevent"、function(){$ scope.count ++;}); } </script> </body> </html>7。スコープライフサイクル(スコープライフサイクル)
ブラウザの通常のイベントストリームでは、ブラウザがイベントを受信すると、対応するJavaScriptコールバックが実行されます。コールバック関数が実行されると、ブラウザはDOMを再描画し、イベントを待ち続ける状態に戻ります。
ブラウザがAngular実行環境の外でJavaScriptコードを呼び出す場合、これはAngularがモデルの変更を知らないことを意味します。モデルの変更を正しく処理するには、このコマンドは$ Applyメソッドを作成してAngular実行環境に入力する必要があります。 $ applyメソッドのモデルが変更された場合にのみ、Angularによって正しくカウントされます。たとえば、指令は、$ applyメソッドの式を評価する必要があるngクリックなどのDOMイベントを聴きます。
式を評価した後、$ applyメソッドは$ダイジェストを実行します。 $ digest段階では、Scopeは$ watchで聞くすべての式をチェックし、現在の値を古い値と比較します。汚いチェックは非同期です。これは、割り当てステートメント(たとえば、$ scope.username = "angular")がすぐに$ watchに通知されることはないことを意味しますが、$ watchの通知は$ digestステージに遅れます。この遅延は、複数のモデルの更新を$ watch通知に組み合わせたため、$ watch通知プロセス中に他の$ watchが実行されないことが保証されます。 $ watchがモデルの値を変更すると、$ digestサイクルの増加が強制されます。
1)作成(作成スコープの作成)
ルートスコープは、アプリケーションスタートアッププロセス中に$ injector(http://code.angularjs.org/1.0.2/docs/api/auto.pered injector)によって作成されます。テンプレートリンクプロセス中に、一部の指令が新しい子スコープを作成します。
2)ウォッチャー登録(登録ウォッチャー)
テンプレートのリンクプロセス中に、ディレクティブはスコープで$ watchを登録します。これらの時計は、モデルをDOMに伝播する価値として使用されます。
3)モデル変異(モデルの変更)
変更を正しく検出するには、それらをスコープでラップする必要があります。$適用。 (Angular APIはこれを暗黙的に行いました。そのため、コントローラーまたは非同期作業で同期作業を行うと、$ HTTPまたは$タイムアウトを使用した場合、追加の$適用コールは必要ありません)。
4)突然変異観察(監視の変更)
$ applyの終わりに、Angularはルートスコープで$ダイジェストサイクルを実行し、すべての子供のスコープに伝播します。 $ digestサイクルでは、$ watchに登録されているすべての式または関数がチェックされ、モデルが変更されたかどうかが判断されます。変更が発生した場合、対応する$ watchリスナーが呼び出されます。
5)スコープ破壊(範囲破壊)
子スコープが不要になった場合、範囲を介してそれらを破壊することは、子スコーププロデューサーの責任です。$ Destroy()API。これにより、子スコープモデルで使用されるメモリをGC(ガーベッジコレクター)でリサイクルできるように、$ DIGESTコールの伝播を子スコープに停止します。
1。スコープと指令
コンパイル段階では、コンパイラはDOMテンプレートマッチングディレクティブに依存しています。通常、ディレクティブは2つのカテゴリに分類できます。
dobule-curly expression {{expression}}などの観察指示は、$ watchメソッドを使用してリスナーを登録します。式(値)が変更されるたびに、そのような指示はビューを更新するために通知する必要があります。
NG-Clickなどのリスナーディレクティブは、リスナーをDOMに登録します。 DOMのリスナーが発射すると、ディレクティブは関連する式を実行し、$ applyメソッドを使用してビューを更新します。
外部イベント(ユーザーアクション、タイマー、XHRなど)が聞こえる場合、すべてのリスナーを正しく更新できるように、$ Applyメソッドを介して関連する式をスコープに適用する必要があります。
2。スコープを作成するディレクティブ
ほとんどの場合、指令と範囲は相互に影響を与えていますが、新しいスコープインスタンスは作成されていません。ただし、一部のディレクティブ(NG-ControllerやNG-Reepeatなど)は、新しいスコープを作成し、対応するDOM要素に子供の範囲を追加します。 Angular.Element(AdomElement).Scope()を使用して、任意のDOM要素の範囲を表示します。
3。コントローラーとスコープ
次の場合、スコープとコントローラーは互いに影響を与えます。
4。スコープ$監視パフォーマンスの考慮事項(スコープ$監視パフォーマンスの考慮事項)
Angularでは、属性の変化を検出するためにスコープで汚れたチェックを実行することは一般的な操作です。これを行うには、汚れたチェック機能が効率的でなければならないことが必要です。 DOMアクセスはJavaScriptオブジェクトプロパティにアクセスするよりも桁違いに遅くなるため、Dirty Checking関数はDOMアクセス操作を実行しないことに注意してください。
上記は、AngularJSスコープに関する情報です。今後も関連情報を追加し続けます。このサイトへのご支援ありがとうございます!