AngularJS は非常に強力なフロントエンド MVC フレームワークです。AngularJS のコントローラーは、ビューのスコープ ($scope) に関数を追加するために使用されます。オブジェクトを作成し、カスタム動作を追加します。
新しいコントローラーを作成するとき、angularJS は新しい $scope オブジェクトを生成してこのコントローラーに渡すのに役立ちます。angularJS アプリケーションのどの部分にも、トップレベルの親スコープがあります。 app が見つかり、その親スコープは $rootScope です。
各 $scope の$root は $rootScope を指し、$cope.$parent は親スコープを指します。
コントローラー間の通信は基本的に、現在のコントローラーが配置されている $scope が他のコントローラーの $scope とどのように通信するかによって決まります。
通常、解決策は 3 つあります:
スコープ継承の原則を使用して、子コントローラーは親コントローラーのコンテンツにアクセスします。 angularJS でイベントを使用します。つまり、メッセージ配信に $on、$emit、$broadcast を使用します。angularJS
でサービスを使用します。
最初の方法
つまり、スコープはスコープ内でネストされます。実際の開発では、このシナリオは比較的まれですが、この方法はより簡単で直接的です。
angularJS のデフォルトでは、現在のスコープで属性が見つからない場合、親スコープで検索され、$rootScope が見つかるまで検索されます。 $rootScope で見つからない場合でも、プログラムは実行されますが、ビューは更新されません。
例
javascript
//Javascript app.controller('ParentController', function($scope) { $scope.person = {greeted: false}; }); app.controller('ChildController', function($scope) { $scope.sayHello = function() { $scope.person.name = 'Ari Lerner'; }; }); //HTML <div ng-controller="ParentController"> <div ng-controller="ChildController"> <a ng-click="sayHello()">Say hello</a> </div> {{ person }} </div> //result {"greeted":true, "name": "Ari Lerner"}
2 番目の方法
スコープは階層的であるため、スコープ チェーンを使用してイベントを渡すことができます。
イベントを配信するには 2 つの方法があります: * $broadcast: トリガーされたイベントは、イベント システム全体に通知するために下方に伝播する必要があります (任意のスコープでこのイベントを処理できるようにします)。 * $emit: グローバル モジュールに通知したい場合は、上位レベルのスコープ ($rootscope など) に通知する必要があるときにイベントを上向きに渡す必要があります。
イベント監視のスコープで $on を使用します。
例
JavaScript
app.controller('ParentController', function($scope) { $scope.$on('$fromSubControllerClick', function(e,data){ console.log(data); // hello }); }); app.controller('ChildController', function($scope) { $scope.sayHello = function() { $scope.$emit('$fromSubControllerClick','hello'); }; }); //HTML <div ng-controller="ParentController"> <div ng-controller="ChildController"> <a ng-click="sayHello()">Say hello</a> </div> </div>
ここでお話したいもう 1 つの問題は、イベント伝播のパフォーマンスの問題です。$broadcast+$on メソッドがすべてのサブスコープに通知する場合、ここでパフォーマンスの問題が発生するため、$emit+$on メソッドを使用することをお勧めします。メソッドのパフォーマンスをさらに向上させるには、スコープが破棄されるときに、定義されたイベント処理関数も一緒に解放する必要があります。
$emit+$on を使用するには、イベント リスナーを $rootScope にバインドする必要があります。例:
JavaScript
angular .module('MyApp') .controller('MyController', ['$scope', '$rootScope', function MyController($scope, $rootScope) { var unbind = $rootScope.$on('someComponent.someCrazyEvent', function(){ console.log('foo'); }); $scope.$on('$destroy', unbind); } ]);
でもこの方法は少し面倒で、複数のイベントハンドリング関数を定義する際に不快になるので改善しましょう
デコレータを使用して新しいイベント バインディング関数を定義します:
JavaScript
angular .module('MyApp') .config(['$provide', function($provide){ $provide.decorator('$rootScope', ['$delegate', function($delegate){ Object.defineProperty($delegate.constructor.prototype, '$onRootScope', { value: function(name, listener){ var unsubscribe = $delegate.$on(name, listener); this.$on('$destroy', unsubscribe); return unsubscribe; }, enumerable: false }); return $delegate; }]); }]);
次に、コントローラーでイベント ハンドラー関数を定義すると:
JavaScript
angular .module('MyApp') .controller('MyController', ['$scope', function MyController($scope) { $scope.$onRootScope('someComponent.someCrazyEvent', function(){ console.log('foo'); }); } ]);
このアプローチを強くお勧めします
第三の方法
angularJS のサービス シングルトン モードの特性を利用して、サービス (サービス) は、アプリケーションのライフサイクル全体を通じてデータを維持し、コントローラー間で通信し、データの一貫性を確保する方法を提供します。
通常、サーバーをカプセル化して、アプリケーションがデータにアクセスしたり、リモートでデータと対話したりするためのインターフェイスを提供します。
例
JavaScript
var myApp = angular.module("myApp", []); myApp.factory('Data', function() { return { name: "Ting" } }); myApp.controller('FirstCtrl', function($scope, Data) { $scope.data = Data; $scope.setName = function() { Data.name = "Jack"; } }); myApp.controller('SecondCtrl', function($scope, Data) { $scope.data = Data; $scope.setName = function() { Data.name = "Moby"; } });
上記は AngularJS コントローラーの正しい通信方法です。皆さんのお役に立てれば幸いです。