$ rootScope. $ широковещание против $ scope. $ emit

349

Теперь, когда разница в производительности между $broadcastи $emitбыла устранена, нет никаких оснований предпочесть , $scope.$emitчтобы $rootScope.$broadcast?

Они разные, да.

$emit ограничено иерархией области действия (вверх) - это может быть хорошо, если оно соответствует вашему дизайну, но мне кажется, это довольно произвольное ограничение.

$rootScope.$broadcastработает во всех, кто хочет слушать событие, что является более разумным ограничением в моем уме.

Я что-то пропустил?

РЕДАКТИРОВАТЬ:

Чтобы уточнить в ответ на ответ, направление отправки не вопрос, который я после. $scope.$emitотправляет событие вверх, а $scope.$broadcastвниз. Но почему не всегда использовать $rootScope.$broadcastдля достижения всех предполагаемых слушателей?

Новый Дев
источник
3
toddmotto.com/… есть все
Divya MV

Ответы:

1155

tl; dr (это tl; dr из ответа @ sp00m ниже)

$emitотправляет событие вверх ... $broadcastотправляет событие вниз

Детальное объяснение

$rootScope.$emitтолько позволяет другим $rootScopeслушателям ловить это. Это хорошо, когда ты не хочешь, чтобы каждый $scopeполучил это. В основном общение высокого уровня. Думайте об этом как о взрослых, разговаривающих друг с другом в комнате, чтобы дети не могли их слышать.

$rootScope.$broadcastэто метод, который позволяет почти всем слышать это. Это было бы равносильно тому, что родители кричат, что ужин готов, поэтому все в доме его слышат.

$scope.$emitэто когда хочется этого $scopeи всем своим родителям и $rootScopeуслышать событие. Это ребенок, который ныет родителям дома (но не в продуктовом магазине, где другие дети могут слышать).

$scope.$broadcastдля $scopeсебя и своих детей. Это ребенок шепчет своим чучелам, чтобы их родители не могли слышать.

Эдди Монж младший
источник
3
@NewDev Причина в том, что часто у вас есть повторение областей на странице. Если у вас есть две или более областей, представляющих разные экземпляры данных - например, список записей пациентов на странице, каждая со своей областью действия - тогда она не будет работать для передачи из корня события, предназначенного только для одного из этих прицелы. Избегание $rootScopeтрансляций, где это возможно, позволяет лучше использовать повторно
Тим Роджерс
4
Ничто из того, что вы сказали, не является неправильным, но есть способ обобщить, что $ emit переводит документ в дочерние области, а $ emit поднимает документ в родительские области. Оба активируют любых слушателей, подключенных к текущей области.
Эрик
123
Пример, который вы использовали, великолепен!
Ассаф
72
Вот Это Да! Даже дети могут понять это! Удивительно :)
Наванет
3
Прекрасный пример, люблю объяснение
Робин-балахон
104

Они не выполняют одну и ту же работу: $emitотправляют событие вверх по иерархии области, а $broadcastсобытие отправляют вниз всем дочерним областям.

sp00m
источник
2
Да, я отметил это в вопросе (возможно, я мог бы дать понять о направлении отправки). Но я также отметил, что это довольно произвольное ограничение. Если я могу связаться со своим «слушателем», почему я не могу всегда делать это вниз $rootScope?
Новый Dev
Потому что $ emit не повлияет на дочерние или родственные области видимости. Они просто сопоставляются с типами распространения событий javascript - захват и пузыри. $ broadcast используется для захвата, а $ emit используется для всплытия. Есть теперь, казалось бы, древняя статья о причудливом режиме, которая довольно хорошо объясняет разницу: quirksmode.org/js/events_order.html
Алан Л.
77

Я сделал следующий рисунок из следующей ссылки: https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribeing/

Область действия, rootScope, излучение, трансляция

Как видите, $rootScope.$broadcastслушателей гораздо больше, чем слушателей $scope.$emit.

Также, $scope.$emitпузырьковый эффект можно отменить, а $rootScope.$broadcastнельзя.

Мария Инес Парнисари
источник
24
Я вижу много стрел.
Марс Робертсон
4
@MichalStefanow Я фанат визуальных ответов :)
Мария Инес Парнисари
@mparnisari: $ broadcast (name, args) - Широковещательная передача события через область действия всех дочерних элементов. $ emit (name, args) - Отправка события по иерархии области действия $ всем родителям, включая $ rootScope
CodeMan
19

введите описание изображения здесь

$ scope. $ emit: этот метод отправляет событие в направлении вверх (от дочернего к родительскому)

введите описание изображения здесь $ scope. $ broadcast: метод отправляет событие в направлении вниз (от родителя к потомку) всем дочерним контроллерам.

введите описание изображения здесь $ scope. $ on: метод регистрирует прослушивание какого-либо события. Все контроллеры, которые прослушивают это событие, получают уведомление о широковещании или излучении в зависимости от того, где они находятся в иерархии дочерних элементов.

Событие $ emit может быть отменено любым из $ scope, который прослушивает событие.

$ On предоставляет метод stopPropagation. При вызове этого метода событие может быть остановлено для дальнейшего распространения.

Плункер: https://embed.plnkr.co/0Pdrrtj3GEnMp2UpILp4/

В случае одноуровневых областей (областей, которые не находятся в прямой иерархии родитель-потомок), $ emit и $ broadcast не будут связываться с одноуровневыми областями.

введите описание изображения здесь

Для получения более подробной информации, пожалуйста, обратитесь к http://yogeshtutorials.blogspot.in/2015/12/event-based-communication-between-angularjs-controllers.html

Yogesh
источник
Ссылка на решение приветствуется, но, пожалуйста, убедитесь, что ваш ответ полезен без нее: добавьте контекст вокруг ссылки, чтобы ваши коллеги-пользователи имели представление о том, что это такое и почему, а затем процитируйте наиболее релевантную часть страницы, которую вы ' Повторная ссылка на случай, если целевая страница недоступна. Ответы, которые немного больше, чем ссылка, могут быть удалены.
Baum mit Augen
Цель состояла в том, чтобы предоставить работающему поршню, однако я добавил здесь соответствующее описание.
Йогеш
3

@ Эдди дал прекрасный ответ на заданный вопрос. Но я хотел бы обратить внимание на использование более эффективного подхода Pub / Sub.

Как следует из этого ответа,

Подход $ broadcast / $ on не очень эффективен, так как он вещает на все области (в одном или обоих направлениях иерархии Scope). Хотя подход Pub / Sub гораздо более прямой. События получают только подписчики, так что не все системы будут работать.

Вы можете использовать angular-PubSubугловой модуль. добавив 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);OR PubSub.unsubscribe('event-name');.

ПРИМЕЧАНИЕ Не забудьте отписаться, чтобы избежать утечек памяти.

vinesh
источник
2

Используйте RxJS в Сервисе

Как насчет ситуации, когда у вас есть Служба, которая удерживает состояние, например. Как я могу отправить изменения в эту Службу и другие случайные компоненты на странице, чтобы быть в курсе таких изменений? В последнее время боролся с этой проблемой

Создайте сервис с расширениями RxJS для 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 .

georgeawg
источник