編集:この回答で対処された問題は、angular.js バージョン1.2.7で解決されています。$broadcast
未登録のスコープでのバブリングを回避し、$ emitと同じくらい高速に実行されるようになりました。
だから、今することができます:
$broadcast
からの使用$rootScope
- イベントについて知る必要が
$on
ある地元の人から$scope
聞いてください
以下の元の回答
$rootScope.$broadcast
+ $scope.$on
ではなく$rootScope.$emit
+ を使用することを強くお勧めします$rootScope.$on
。前者は@numanによって引き起こされる深刻なパフォーマンスの問題を引き起こす可能性があります。これは、イベントがすべてのスコープを通過するためです。
ただし、後者($rootScope.$emit
+ を使用$rootScope.$on
)ではこの問題が発生しないため、高速通信チャネルとして使用できます。
の角度のドキュメントから$emit
:
登録されていることを通知するスコープ階層を通じてイベント名を上方にディスパッチします
上記のスコープがないため$rootScope
、バブリングは発生していません。EventBusとして$rootScope.$emit()
/ を使用しても完全に安全$rootScope.$on()
です。
ただし、コントローラ内から使用する場合、1つの問題があります。$rootScope.$on()
コントローラ内から直接バインドする場合、ローカル$scope
が破壊されたときに自分でバインドをクリーンアップする必要があります。これは、コントローラーが(サービスとは対照的に)アプリケーションの存続期間中に複数回インスタンス化される可能性があるためです。その結果、バインディングが合計され、最終的に場所全体にメモリリークが発生します。
登録を解除するには、$scope
の$destroy
イベントをリッスンし、から返された関数を呼び出します$rootScope.$on
。
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);
}
]);
他のEventBus実装にも当てはまるので、リソースをクリーンアップする必要があるというのは、実際には角度によるものではありません。
ただし、それらの場合には、あなたの人生を楽にすることができます。たとえば、サルのパッチ$rootScope
を適用して、$onRootScope
で発行されたイベントをサブスクライブし$rootScope
、ローカル$scope
が破棄されたときにハンドラを直接クリーンアップすることもできます。
その$rootScope
ような$onRootScope
メソッドを提供するためにサルのパッチを適用する最もクリーンな方法は、デコレータを使用することです(runブロックはおそらくそれでもうまくいきますが、誰にも言わないでください)。
確認するために$onRootScope
上で列挙するときに、プロパティが予期しない表示されません。$scope
私たちが使用Object.defineProperty()
して設定enumerable
しますfalse
。ES5シムが必要になる場合があることに注意してください。
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;
}]);
}]);
このメソッドを配置すると、上記のコントローラーコードを次のように簡略化できます。
angular
.module('MyApp')
.controller('MyController', ['$scope', function MyController($scope) {
$scope.$onRootScope('someComponent.someCrazyEvent', function(){
console.log('foo');
});
}
]);
したがって、このすべての最終結果として、$rootScope.$emit
+ を使用することを強くお勧めします$scope.$onRootScope
。
ところで、私は角度のあるチームに角度のあるコア内の問題に対処するよう説得しようとしています。ここで議論が行われています:https : //github.com/angular/angular.js/issues/4574
次のjsperfは、$broadcast
わずか100 $scope
の適切なシナリオで、perfの影響がどの程度テーブルにもたらすかを示しています。
http://jsperf.com/rootscope-emit-vs-rootscope-broadcast