回答:
まず、親子スコープの関係が重要です。イベントを発生させる方法は2つあります。
$broadcast
-イベントをすべての子スコープに送信します。$emit
-スコープ階層を介して上方向にイベントをディスパッチします。コントローラー(スコープ)の関係については何も知りませんが、いくつかのオプションがあります。
スコープがスコープのfirstCtrl
親であるsecondCtrl
場合、コードは次のように置き換える$emit
こと$broadcast
で機能しfirstCtrl
ます。
function firstCtrl($scope)
{
$scope.$broadcast('someEvent', [1,2,3]);
}
function secondCtrl($scope)
{
$scope.$on('someEvent', function(event, mass) { console.log(mass); });
}
スコープ間に親子関係がない場合は$rootScope
、コントローラーに注入して、すべての子スコープ(つまりsecondCtrl
)にイベントをブロードキャストできます。
function firstCtrl($rootScope)
{
$rootScope.$broadcast('someEvent', [1,2,3]);
}
最後に、子コントローラーからスコープの上にイベントを送出する必要がある場合は、を使用できます$scope.$emit
。スコープがスコープのfirstCtrl
親である場合secondCtrl
:
function firstCtrl($scope)
{
$scope.$on('someEvent', function(event, data) { console.log(data); });
}
function secondCtrl($scope)
{
$scope.$emit('someEvent', [1,2,3]);
}
$rootScope
、サービスに注入して、サービスからイベントをブロードキャストできます。
$rootScope
、サービス(から$rootScope
)からイベントを発行した場合でも、イベントがパーコレーションすることを知りたいです$rootScope
。なぜなら、$broadcast
階層をDOWNに$emit
パーコレートし、UPにパーコレートする場合-ブロードキャスター/エミッターはリスナー(?)でもあるため、「UP」と「DOWN」の間に何が起こるかです。イベントをすべての「UPWARD」およびすべての「DOWNWARD」スコープに対してサイレントにしたいが、ディスパッチャと同じレベルでのみ「聞こえる」ようにするにはどうすればよいですか?
さらに、@ zbynourによって提案されたオプションのより良い代替手段として、4番目のオプションを提案します。
$rootScope.$emit
ではなく使用$rootScope.$broadcast
関係なく、コントローラをtrasmittingと受信との関係。そのように、一連の内部イベントが残る$rootScope.$$listeners
とのに対し$rootScope.$broadcast
、おそらく、とにかくそのイベントのリスナーではありませんほとんどが、すべての子供たちのスコープにイベントが伝播します。そしてもちろん、受信側のコントローラでは、を使用するだけ$rootScope.$on
です。
このオプションでは、コントローラーのrootScopeリスナーを破棄することを忘れないでください。
var unbindEventHandler = $rootScope.$on('myEvent', myHandler);
$scope.$on('$destroy', function () {
unbindEventHandler();
});
$rootScope
コントローラーへの注入が必要になります(一般的には必要ありません)。しかし、確かに別のオプション、thx!
。$ emitメソッドと。$ onメソッドを使用して、1つのコントローラーから別のコントローラーに$ scopeオブジェクトを送信するにはどうすればよいですか?
$ scopeを含め、アプリの階層内で必要なオブジェクトを送信できます。
ブロードキャストとエミットがどのように機能するかについて簡単に説明します。
以下のノードに注意してください。ノード3内にすべてネストされています。このシナリオでは、ブロードキャストとエミットを使用します。
注:この例の各ノードの数は任意です。それは簡単に一番です。数2; または1,348です。各番号は、この例の単なる識別子です。この例のポイントは、Angularコントローラ/ディレクティブのネストを示すことです。
3
------------
| |
----- ------
1 | 2 |
--- --- --- ---
| | | | | | | |
この木をチェックしてください。次の質問にどのように答えますか?
注:これらの質問に答える方法は他にもありますが、ここではブロードキャストとエミットについて説明します。また、以下のテキストを読むとき、各番号には、one.js、two.js、three.jsなどの独自のファイル(ディレクティブ、コントローラー)があると仮定します。
ノード1はノード3とどのように通信しますか?
ファイルone.js
scope.$emit('messageOne', someValue(s));
ファイルthree.js-通信に必要なすべての子ノードの最上位ノード。
scope.$on('messageOne', someValue(s));
ノード2はノード3とどのように通信しますか?
ファイルtwo.js
scope.$emit('messageTwo', someValue(s));
ファイルthree.js-通信に必要なすべての子ノードの最上位ノード。
scope.$on('messageTwo', someValue(s));
ノード3はノード1やノード2とどのように通信しますか?
ファイルthree.js-通信に必要なすべての子ノードの最上位ノード。
scope.$broadcast('messageThree', someValue(s));
ファイルone.js && two.jsで、メッセージをキャッチしたいファイル、またはその両方。
scope.$on('messageThree', someValue(s));
ノード2はノード1とどのように通信しますか?
ファイルtwo.js
scope.$emit('messageTwo', someValue(s));
ファイルthree.js-通信に必要なすべての子ノードの最上位ノード。
scope.$on('messageTwo', function( event, data ){
scope.$broadcast( 'messageTwo', data );
});
ファイルone.js
scope.$on('messageTwo', someValue(s));
しかしながら
これらのネストされたすべての子ノードがこのように通信しようとすると、多くの$ on、$ broadcast、および$ emitがすぐに表示されます。
これが私がやりたいことです。
最上部のPARENT NODE(この場合は3)で、これは親コントローラーである可能性があります...
したがって、three.jsファイルで
scope.$on('pushChangesToAllNodes', function( event, message ){
scope.$broadcast( message.name, message.data );
});
これで、どの子ノードでも、メッセージを$ emitするか、$ onを使用してそれをキャッチするだけです。
注:通常、$ emit、$ broadcast、または$ onを使用せずに1つのネストされたパスでクロストークすることは非常に簡単です。つまり、ほとんどのユースケースは、ノード1をノード2と通信させたり、その逆を行う場合です。
ノード2はノード1とどのように通信しますか?
ファイルtwo.js
scope.$emit('pushChangesToAllNodes', sendNewChanges());
function sendNewChanges(){ // for some event.
return { name: 'talkToOne', data: [1,2,3] };
}
ファイルthree.js-通信に必要なすべての子ノードの最上位ノード。
私たちはすでにこれを処理しました覚えていますか?
ファイルone.js
scope.$on('talkToOne', function( event, arrayOfNumbers ){
arrayOfNumbers.forEach(function(number){
console.log(number);
});
});
キャッチする特定の値ごとに$ onを使用する必要がありますが、キャッチしてブロードキャストするときに親ノードのギャップを越えてメッセージを取得する方法を心配する必要なく、どのノードでも好きなように作成できます。一般的なpushChangesToAllNodes。
お役に立てれば...
The event life cycle starts at the scope on which $broadcast was called. All listeners listening for name event on this scope get notified.
と$on('x', function(e, data) { $broadcast('x', data) })
、ctrl3でctrl2と通信するctrl1を実装すると、(私のような)無限ループが発生します。放送する前にこれらの回線が必要になります。if (e.targetScope.$id === $scope.$id) { return; }
$scope object
あるコントローラーから別のコントローラーに送信するために$rootScope.$broadcast
、$rootScope.$emit
こことここで説明します。
ケース1:
$ rootScope。$ broadcast:-
$rootScope.$broadcast('myEvent',$scope.data);//Here `myEvent` is event name
$rootScope.$on('myEvent', function(event, data) {} //listener on `myEvent` event
$rootScope
リスナーは自動的に破棄されません。を使用して破壊する必要があり$destroy
ます。$scope.$on
上のリスナー$scope
は自動的に破棄されるため、つまり$ scopeが破棄されるとすぐに使用することをお勧めします。
$scope.$on('myEvent', function(event, data) {}
または、
var customeEventListener = $rootScope.$on('myEvent', function(event, data) {
}
$scope.$on('$destroy', function() {
customeEventListener();
});
ケース2:
$ rootScope。$ emit:
$rootScope.$emit('myEvent',$scope.data);
$rootScope.$on('myEvent', function(event, data) {}//$scope.$on not works
$ emitと$ broadcastの主な違いは、$ rootScope。$ emitイベントは$ rootScope。$ onを使用してリッスンする必要があるということです。これは、発行されたイベントがスコープツリーを通過することがないためです。。
この場合も、$ broadcastの場合と同様に、リスナーを破棄する必要があります。
編集:
使いたくない
$rootScope.$broadcast + $scope.$on
が使いたい$rootScope.$emit+ $rootScope.$on
。$rootScope.$broadcast + $scope.$on
コンボは、重大なパフォーマンス上の問題を引き起こす可能性があります。これは、イベントがすべてのスコープを通過するためです。
編集2:
この回答で対処された問題は、angular.jsバージョン1.2.7で解決されています。$ broadcastは未登録のスコープをバブリングすることを回避し、$ emitと同じくらい速く実行されます。
同じアプリ内のコントローラー間でイベントを送信およびキャプチャするには、$ rootScopeを使用する必要があります。$ rootScope依存関係をコントローラーに注入します。これが実際の例です。
app.controller('firstCtrl', function($scope, $rootScope) {
function firstCtrl($scope) {
{
$rootScope.$emit('someEvent', [1,2,3]);
}
}
app.controller('secondCtrl', function($scope, $rootScope) {
function secondCtrl($scope)
{
$rootScope.$on('someEvent', function(event, data) { console.log(data); });
}
}
$ scopeオブジェクトにリンクされたイベントは、オーナーコントローラーでのみ機能します。コントローラ間の通信は、$ rootScopeまたはサービスを介して行われます。
コントローラーからサービスを呼び出してpromiseを返し、それをコントローラーで使用できます。さらに、$emit
または$broadcast
を使用して、他のコントローラーに通知します。私の場合、サービスを通じてhttp呼び出しを行う必要があったので、次のようなことをしました。
function ParentController($scope, testService) {
testService.getList()
.then(function(data) {
$scope.list = testService.list;
})
.finally(function() {
$scope.$emit('listFetched');
})
function ChildController($scope, testService) {
$scope.$on('listFetched', function(event, data) {
// use the data accordingly
})
}
そして私のサービスはこのようになります
app.service('testService', ['$http', function($http) {
this.list = [];
this.getList = function() {
return $http.get(someUrl)
.then(function(response) {
if (typeof response.data === 'object') {
list = response.data.results;
return response.data;
} else {
// invalid response
return $q.reject(response.data);
}
}, function(response) {
// something went wrong
return $q.reject(response.data);
});
}
}])
これは私の機能です:
$rootScope.$emit('setTitle', newVal.full_name);
$rootScope.$on('setTitle', function(event, title) {
if (scope.item)
scope.item.name = title;
else
scope.item = {name: title};
});
<!DOCTYPE html>
<html>
<head>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
var app = angular.module('MyApp',[]);
app.controller('parentCtrl',function($scope){
$scope.$on('MyEvent',function(event,data){
$scope.myData = data;
});
});
app.controller('childCtrl',function($scope){
$scope.fireEvent = function(){
$scope.$emit('MyEvent','Any Data');
}
});
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="parentCtrl" ng-model="myName">
{{myData}}
<div ng-controller="childCtrl">
<button ng-click="fireEvent()">Fire Event</button>
</div>
</div>
</body>
</html>
スコープを使用して、イベントをスコープの子または親に伝播、ディスパッチできます。
$ emit-イベントを親に伝搬します。$ broadcast-イベントを子に伝播します。 $ on-$ emitと$ broadcastによって伝播されるイベントをリッスンするメソッド。
index.htmlの例:
<div ng-app="appExample" ng-controller="EventCtrl">
Root(Parent) scope count: {{count}}
<div>
<button ng-click="$emit('MyEvent')">$emit('MyEvent')</button>
<button ng-click="$broadcast('MyEvent')">$broadcast('MyEvent')</button><br>
Childrent scope count: {{count}}
</div>
</div>
app.jsの例:
angular.module('appExample', [])
.controller('EventCtrl', ['$scope', function($scope) {
$scope.count = 0;
$scope.$on('MyEvent', function() {
$scope.count++;
});
}]);
ここでコードをテストできます:http : //jsfiddle.net/zp6v0rut/41/
以下のコードは、イベントが上位の親コントローラー(rootScope)にディスパッチされる2つのサブコントローラーを示しています。
<body ng-app="App">
<div ng-controller="parentCtrl">
<p>City : {{city}} </p>
<p> Address : {{address}} </p>
<div ng-controller="subCtrlOne">
<input type="text" ng-model="city" />
<button ng-click="getCity(city)">City !!!</button>
</div>
<div ng-controller="subCtrlTwo">
<input type="text" ng-model="address" />
<button ng-click="getAddrress(address)">Address !!!</button>
</div>
</div>
</body>
var App = angular.module('App', []);
// parent controller
App.controller('parentCtrl', parentCtrl);
parentCtrl.$inject = ["$scope"];
function parentCtrl($scope) {
$scope.$on('cityBoom', function(events, data) {
$scope.city = data;
});
$scope.$on('addrBoom', function(events, data) {
$scope.address = data;
});
}
// sub controller one
App.controller('subCtrlOne', subCtrlOne);
subCtrlOne.$inject = ['$scope'];
function subCtrlOne($scope) {
$scope.getCity = function(city) {
$scope.$emit('cityBoom', city);
}
}
// sub controller two
App.controller('subCtrlTwo', subCtrlTwo);
subCtrlTwo.$inject = ["$scope"];
function subCtrlTwo($scope) {
$scope.getAddrress = function(addr) {
$scope.$emit('addrBoom', addr);
}
}
angularjsイベントドキュメントによると、受信側には次のような構造の引数が含まれているはずです
@params
-{Object}イベントは、イベントに関する情報を含むイベントオブジェクトです
-呼び出し先によって渡される{Object}引数(これは、常にディクショナリオブジェクトで送信する方がよいので、1つだけであることに注意してください)
$scope.$on('fooEvent', function (event, args) { console.log(args) });
あなたのコードから
また、異なるコントローラ間で共有される情報を取得しようとしている場合、それを実現する別の方法があります。これは、角度のあるサービスです。サービスはシングルトンであるため、コントローラ間で情報を格納およびフェッチできます。単純にgetterを作成し、そのサービス内のセッター関数、これらの関数を公開し、サービス内にグローバル変数を作成し、それらを使用して情報を格納します
最も簡単な方法:
HTML
<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="sendData();"> Send Data </button>
</div>
JavaScript
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $rootScope) {
function sendData($scope) {
var arrayData = ['sam','rumona','cubby'];
$rootScope.$emit('someEvent', arrayData);
}
});
app.controller('yourCtrl', function($scope, $rootScope) {
$rootScope.$on('someEvent', function(event, data) {
console.log(data);
});
});
</script>
$rootScope
回避できる場合は、ブロードキャスト/エミットに使用しないでください。