编辑:此答案中解决的问题已在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
,所以不会发生冒泡。将$rootScope.$emit()
/ $rootScope.$on()
用作EventBus 是完全安全的。
但是,从Controllers中使用它时只有一个陷阱。如果直接$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
,以订阅on发出的事件,$rootScope
但也可以在本地$scope
被销毁时直接清理处理程序。
$rootScope
提供这种$onRootScope
方法的最简单的方法就是通过装饰器(运行块也可以做到这一点,但是pssst,不要告诉任何人)
为确保该$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
。
http://jsperf.com/rootscope-emit-vs-rootscope-broadcast