$ rootScope. $broadcast vs. $scope. $emit
Теперь, когда разница в производительности между $broadcast
и $emit
была устранена, есть ли какая-либо причина предпочесть от $scope.$emit
до $rootScope.$broadcast
?
Они разные, да.
$emit
ограничен иерархией области (вверх) - это может быть хорошо, если оно соответствует вашему дизайну, но мне кажется, что это довольно произвольное ограничение.
$rootScope.$broadcast
работает во всех, кто предпочитает слушать событие, что является более разумным ограничением в моем сознании.
Я что-то пропустил?
EDIT:
Чтобы пояснить ответ в ответ, направление отправки не является проблемой, за которой я нуждаюсь. $scope.$emit
отправляет событие вверх, а $scope.$broadcast
- вниз. Но почему бы не всегда использовать $rootScope.$broadcast
для охвата всех предполагаемых слушателей?
Ответы
Ответ 1
tl; dr (это tl; dr от @sp00m ниже)
$emit
отправляет событие вверх... $broadcast
отправляет событие вниз
Подробное объяснение
$rootScope.$emit
позволяет другим слушателям $rootScope
уловить его. Это хорошо, когда вы не хотите, чтобы каждый $scope
получил его. В основном связь высокого уровня. Подумайте об этом, когда взрослые разговаривают друг с другом в комнате, чтобы дети не могли их услышать.
$rootScope.$broadcast
- это метод, который позволяет почти все слышать его. Это было бы равносильно тому, что родители кричали, что ужин готов, чтобы все в доме его услышали.
$scope.$emit
- это когда вы хотите, чтобы $scope
и все его родители и $rootScope
услышали это событие. Это ребенок, скулящий к родителям дома (но не в продуктовом магазине, где могут слышать другие дети).
$scope.$broadcast
для самого $scope
и его дочерних элементов. Это ребенок, шепчущий своим чучелам, чтобы их родители не слышали.
Ответ 2
Они не выполняют одно и то же задание: $emit
отправляет событие вверх по иерархии областей, а $broadcast
отправляет событие вниз во все дочерние области.
Ответ 3
Я сделал следующий рисунок из следующей ссылки: https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/
![Scope, rootScope, emit, broadcast]()
Как вы можете видеть, $rootScope.$broadcast
показывает гораздо больше слушателей, чем $scope.$emit
.
Кроме того, эффект $scope.$emit может быть отменен, тогда как $rootScope.$broadcast
не может.
Ответ 4
![введите описание изображения здесь]()
$scope. $emit: этот метод отправляет событие в направлении вверх (от дочернего к родительскому)
$ scope. $broadcast: метод отправляет событие в направлении вниз (от родителя к дочернему) ко всем дочерним контроллерам.
$ scope. $on: Методические регистры для прослушивания некоторого события. Все контроллеры, которые слушают это событие, получают уведомление о трансляции или испускании на основе
где они соответствуют иерархии дочерних и родительских.
Событие $emit может быть отменено любым из $scope, который слушает событие.
$on предоставляет метод stopPropagation. Вызывая этот метод, событие может быть остановлено от дальнейшего распространения.
Plunker: https://embed.plnkr.co/0Pdrrtj3GEnMp2UpILp4/
В случае областей брака (области, которые не находятся в иерархии прямого родительского и дочернего), $emit и $broadcast не будут сообщаться с областями брака.
![введите описание изображения здесь]()
Для получения дополнительной информации см.
http://yogeshtutorials.blogspot.in/2015/12/event-based-communication-between-angularjs-controllers.html
Ответ 5
@Эдди дал прекрасный ответ на заданный вопрос.
Но я хотел бы обратить внимание на использование более эффективного подхода к Pub/Sub.
Как этот говорит,
Подход $broadcast/$on не очень эффективен, поскольку он транслирует все области (либо в одном направлении, либо в обоих направлениях иерархии Scope). В то время как подход Pub/Sub намного более прямой. Только подписчики получают события, поэтому он не подходит к каждой области в системе, чтобы заставить ее работать.
вы можете использовать angular-PubSub
angular модуль. как только вы добавите модуль PubSub
к зависимости вашего приложения, вы можете использовать службу PubSub
для подписки и отмены подписки на события/темы.
Легко подписаться:
// Subscribe to event
var sub = PubSub.subscribe('event-name', function(topic, data){
});
Легко публиковать
PubSub.publish('event-name', {
prop1: value1,
prop2: value2
});
Чтобы отказаться от подписки, используйте PubSub.unsubscribe(sub);
ИЛИ PubSub.unsubscribe('event-name');
.
ПРИМЕЧАНИЕ Не забывайте отменять подписку, чтобы избежать утечек памяти.
Ответ 6
Использовать RxJS в службе
Как насчет ситуации, когда у вас есть Служба, которая удерживает состояние, например. Как я могу нажать на изменения в этой Службе, и другие случайные компоненты на странице должны знать о таком изменении? Борьба с решением этой проблемы в последнее время
Создайте сервис с RxJS Extensions для Angular.
<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/rx/dist/rx.all.js"></script>
<script src="//unpkg.com/rx-angular/dist/rx.angular.js"></script>
var app = angular.module('myApp', ['rx']);
app.factory("DataService", function(rx) {
var subject = new rx.Subject();
var data = "Initial";
return {
set: function set(d){
data = d;
subject.onNext(d);
},
get: function get() {
return data;
},
subscribe: function (o) {
return subject.subscribe(o);
}
};
});
Затем просто подпишитесь на изменения.
app.controller('displayCtrl', function(DataService) {
var $ctrl = this;
$ctrl.data = DataService.get();
var subscription = DataService.subscribe(function onNext(d) {
$ctrl.data = d;
});
this.$onDestroy = function() {
subscription.dispose();
};
});
Клиенты могут подписаться на изменения с помощью DataService.subscribe
, и производители могут нажать изменения с помощью DataService.set
.
DEMO на PLNKR.