Редактировать : проблема, затронутая в этом ответе, была решена в 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.
Однако при использовании изнутри контроллеров есть один недостаток. Если вы выполняете прямую привязку к $rootScope.$on()контроллеру изнутри, вам придется самостоятельно очищать привязку при $scopeразрушении вашей локальной системы . Это связано с тем, что контроллеры (в отличие от сервисов) могут создаваться несколько раз за время жизни приложения, что приведет к суммированию привязок, что в конечном итоге приведет к утечкам памяти повсюду :)
Чтобы отменить регистрацию, просто слушать на вашем $scope«S $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, вероятно, тоже отлично это сделает, но 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.
Кстати, я пытаюсь убедить команду разработчиков Angular решить проблему в рамках ядра Angular. Здесь идет обсуждение: https://github.com/angular/angular.js/issues/4574
Вот jsperf, который показывает, сколько перфектного воздействия $broadcastприносит на стол при достойном сценарии всего за 100 $scopeс.
http://jsperf.com/rootscope-emit-vs-rootscope-broadcast
