AngularJSにおける$scopeとは何ですか?例を用いたチュートリアル

⚡ スマートサマリー

AngularJS の $Scope は、コントローラとビューをバインドする組み込みオブジェクトです。このページでは、スコープの作成、動作関数、親と子の階層構造、$rootScope との違い、およびダイジェストサイクルによるバインディングの更新方法について説明します。

  • 🔗 バインディングロール: $scope は、コントローラからビューにメンバ変数を渡すため、テンプレートは DOM に直接アクセスすることなくデータをレンダリングできます。
  • ⚙️ 動作機能: ビューがクリック、入力値の変更、その他のユーザーイベントに反応する必要がある場合は、$scope に関数をアタッチします。
  • 🌳 スコープ階層: ng-controllerやng-repeatなどのディレクティブは、アプリケーションのDOMツリーを反映する子スコープを作成します。
  • 🌍 $rootScope 到達範囲: アプリケーションごとに1つの$rootScopeが存在し、すべての子スコープが読み取ることができるグローバルオブジェクトのように動作します。
  • 🔍 消化サイクル: $watch はリスナーを登録し、$apply は AngularJS の実行コンテキストに入り、$digest はモデルが安定するまで値を比較します。
  • 🚀 パフォーマンス習慣: ウォッチ式はできるだけ軽量に保ち、内部でのDOMアクセスは避け、不要になったスコープは$destroyを呼び出してください。

AngularJSにおける$Scopeとは何ですか?

AngularJS の $scope とは何ですか?

AngularJS の $scope 基本的に「コントローラー」と「ビュー」をバインドする組み込みオブジェクトです。 コントローラー内のスコープでメンバー変数を定義すると、ビューからアクセスできます。

すべてのコントローラー AngularJS アプリケーションは依存性注入によって独自の $scope インスタンスを受け取ります。そのオブジェクトにアタッチしたものはすべて、コントローラが管理するテンプレートから見えるようになります。そのため、$scope は、アプリケーションとコントローラの間にある共有データ モデルとして機能します。 JavaスクリプトのロジックとHTMLマークアップ。

以下の例を考えてみましょう。

AngularJS の $scope

angular.module('app',[]).controller('HelloWorldCtrl',
	function($scope)
	{
		$scope.message = "Hello World"
	});

Code 説明:

  1. モジュールの名前は「アプリ」です
  2. コントローラーの名前は「HelloWorldCtrl」です。
  3. Scope オブジェクトは、コントローラーからビューに情報を渡すために使用される主要なオブジェクトです。
  4. メンバー変数がスコープオブジェクトに追加されました

⚠️ 構文警告: その .controller() メソッドはコントローラ名とファクトリ関数の 2 つの引数を取るので、間にカンマが必要です 'HelloWorldCtrl' (NAIST) と function($scope). コンマを省略すると、 Uncaught SyntaxError AngularJSが起動する前。

単一のコントローラーと単一のビューだけでは、全体像の半分しか捉えられません。実際のアプリケーションでは、コントローラーがネストされ、リストが繰り返し使用され、ウィジェットが再利用されるため、複数のスコープが同時に存在します。

AngularJSにおけるスコープ階層と継承の仕組み

AngularJSアプリケーションには必ず1つのルートスコープがあり、子スコープはいくつでも持つことができます。ディレクティブはこれらの子スコープを作成し、装飾するDOM要素にアタッチするため、スコープツリーはレンダリングされたページの構造を反映します。

AngularJS が次のような式を評価するとき {{siteName}}まず、要素にアタッチされたスコープでそのプロパティを探します。プロパティが存在しない場合は、親スコープに検索範囲が移り、ルートスコープに到達するまで検索を続けます。 Javaスクリプト開発者はこの動作をプロトタイプ継承と呼び、子スコープはまさにそのようにして親スコープから継承します。

以下の例では、コントローラーを別のコントローラーの中にネストすることで、継承がどのように行われるかを確認できます。

<div ng-app="scopeDemo">
    <div ng-controller="ParentCtrl">
        Parent scope value: {{siteName}}
        <div ng-controller="ChildCtrl">
            Child reads parent value: {{siteName}}
            Child own value: {{lesson}}
        </div>
    </div>
</div>

<script type="text/javascript">
    var app = angular.module("scopeDemo", []);

    app.controller("ParentCtrl", function($scope) {
        $scope.siteName = "Guru99";
    });

    app.controller("ChildCtrl", function($scope) {
        $scope.lesson = "AngularJS Scope";
    });
</script>

Code 説明:

  1. ParentCtrl 定義 siteName それ自身の範囲内で。
  2. ChildCtrl 定義しない siteNameしかし、内部のdivは依然として Guru99 なぜなら、ルックアップは親スコープまで遡るからです。
  3. lesson 子要素のスコープ内でのみ存在するため、親要素のdivからは読み取ることができません。

どの指示によって新しいスコープが作成されますか?

  • ng-controller: 配置先の要素に対して子スコープを作成します。
  • ng-repeat: 反復処理ごとに1つの子スコープが作成されるため、各行は同じ式に対して異なる値を保持できます。
  • カスタム指示: 子どものスコープを要求するか、 隔離する 意図的に親クラスから継承しないスコープ。
  • コンポーネント指示: 登録されているもの .component() ヘルパーは常に分離スコープを受け取ります。

子スコープは上位レベルまで読み込まれるため、開発者はしばしばそのチェーンの最上位がどこにあるのか疑問に思うことがあります。その最上位オブジェクトは$rootScopeと呼ばれます。

$scopeと$rootScopeの違いは何ですか?

AngularJS $rootScope はアプリケーション全体のスコープです。アプリケーションには $rootScope が 1 つしか存在できず、グローバル変数のように使用されます。すべての $scope は子スコープであり、$rootScope はツリーの最上位にある親スコープです。以下の表は、これら 2 つのオブジェクトを比較したものです。

側面 $スコープ $rootScope
アプリケーションごとのインスタンス数 コントローラーまたはスコープ作成ディレクティブごとに1つずつ、多数存在する。 ちょうど1つ
によって作成された ng-controller や ng-repeat などのディレクティブ アプリケーション起動時のインジェクター
透明性 その元素とそのすべての子孫 アプリケーション内のすべてのスコープ
典型的な使用 1つのビューまたは1つのリスト行のデータと動作 アプリケーション全体の値(ログインユーザーなど)
主なリスク ブランチ外では値にアクセスできなくなります 名前衝突や隠れた結合(グローバル変数など)

$rootScope は控えめに使用してください。そこに配置したものはアプリケーション全体で存在し、どこからでも読み取り可能になるため、通常は共有サービスの方がグローバルステートの安全な場所となります。 $rootScope 参照 完全なAPI一覧が表示されます。

データの保存場所を把握することは、仕事の半分に過ぎません。残りの半分は、ユーザーが何らかの操作を行った際に、スコープがどのように反応するかを教えることです。

AngularJSで動作を設定または追加する

イベントに反応したり、ビュー内で何らかの計算/処理を実行したりするには、スコープに動作を提供する必要があります。

ビヘイビアーは、ビューによってトリガーされる可能性のある特定のイベントに応答するためにスコープ オブジェクトに追加されます。 コントローラーで動作を定義すると、ビューからアクセスできるようになります。

これを実現する方法の例を見てみましょう。

動作の設定または追加

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta chrset="UTF 8">
    <title>Guru99</title>     
</head>  
<body ng-app="DemoApp">
<h1> Guru99 Global Event</h1>
<script src="https://code.angularjs.org/1.6.9/angular.js"></script>
<div ng-controller="DemoController">
	{{fullName("Guru","99")}}
</div>
<script type="text/javascript">  
	var app = angular.module("DemoApp", []);
	app.controller("DemoController", function($scope) {
    
    $scope.fullName=function(firstName,lastname){
		return firstName + lastname;
		}
	} );
</script> 

</body>  
</html>

Code 説明:

  1. 「fullName」という動作を作成しています。 この動作は、2 つのパラメーター (firstName、lastname) を受け入れる関数です。
  2. その後、動作はこれら 2 つのパラメーターを連結したものを返します。
  3. ビューでは、動作を呼び出し、2 つの値を渡しています。Guru」と「99」は、動作のパラメータとして渡されます。

コマンドが正常に実行された場合、ブラウザでコードを実行すると次の出力が表示されます。

出力:

動作の設定または追加

ブラウザには、両方の値の連結が表示されます。 Guru 99 は、 コントローラ.

上記のようなバインディングは自動的に更新されるため、アプリケーションが大規模になる前に、その仕組みを理解しておくことは重要です。

スコープウォッチャーとダイジェストサイクルが重要な理由

AngularJSは、変更イベントではなくダーティチェックによってビューをスコープと同期させます。このプロセスは、以下の3つのスコープAPIによって実現されます。

  • $watch: 式のリスナーを登録します。補間式は、 {{fullName}} テンプレートのリンク時に、監視者を自動的に登録します。
  • $適用: AngularJSの実行コンテキストに入り、コードを評価してからダイジェストをトリガーします。組み込みのディレクティブは既にこの関数を呼び出すため、カスタムイベントコールバックまたはサードパーティライブラリのコールバック内でのみ必要です。
  • $digest: $rootScopeとその子要素上のすべてのウォッチャーを走査し、現在の値を前の値と比較し、モデルが変更されなくなるまで繰り返します。

ダイジェストは複数回実行される可能性があるため、ウォッチ式は低コストに保つ必要があります。DOM の読み取りは、データの読み取りよりも桁違いに遅いため、ウォッチ式内で DOM アクセスは避けてください。 Javaスクリプトプロパティ。

監視の深さもコストに影響します。参照による監視は最も速く、価値全体が交換されたときにのみ検知します。 $watchCollection 配列またはオブジェクト内で追加、削除、または並べ替えられた項目を通知します。値による監視は、ダイジェストごとにネストされた構造を走査するため、最もコストのかかるオプションです。したがって、最後に使用するようにしてください。

よくあるご質問

分離スコープは、親からプロトタイプを継承しません。.component() ヘルパーを使用して作成されたコンポーネントディレクティブは常に分離スコープを受け取ります。これにより、再利用可能なウィジェットが周囲のコントローラから独立した状態を保ち、親プロパティへの意図しない読み取りを防ぎます。

$emit はスコープイベントを親スコープを経由して $rootScope まで送信し、$broadcast はそれをすべての子スコープまで送信します。どちらも $on で受信されます。$broadcast はすべての子孫スコープを通過するため、使用は控えめにしてください。

子スコープが不要になったら、scope.$destroy() を呼び出してください。これにより、スコープへのダイジェストの伝播が停止し、ガベージコレクタがモデルを回収できるようになります。また、$watch が返す関数を呼び出して、手動ウォッチャーの登録も解除してください。

アシスタントなど GitHubコパイロット スコープの定型文を素早く生成できますが、コントローラー登録のカンマの欠落などのミスが発生することがあります。生成されたすべてのスニペットを公式の AngularJSスコープに関するドキュメント.

AIアシスタントは、$scopeプロパティをコンポーネントクラスのフィールドにマッピングし、$watchロジックをシグナルまたはRxJSストリームとして書き換えます。公式と組み合わせると 角度の 生成された変換では継承スコープの参照が欠落していることが多いため、ドキュメントを作成し、単体テストを実行してください。