$ rootScope. $ трансляція порівняно з $ range. $ emit


349

Тепер, коли різниця в продуктивності між $broadcastі$emit була усунена, немає ніяких підстав вважати за краще , $scope.$emitщоб $rootScope.$broadcast?

Вони різні, так.

$emit обмежується ієрархією обсягу (вгору) - це може бути добре, якщо воно відповідає вашому дизайну, але мені це здається досить довільним обмеженням.

$rootScope.$broadcast працює в усьому цьому вирішив послухати подію, що є більш розумним обмеженням на мою думку.

Я щось пропускаю?

Редагувати:

Щоб уточнити у відповідь на відповідь, напрямок відправки - це не питання, про яке я пішов. $scope.$emitрозсилає подію вгору, а $scope.$broadcast- вниз. Але чому б не завжди використовувати, $rootScope.$broadcastщоб охопити всіх призначених слухачів?


Відповіді:


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
Оце Так! Навіть діти можуть це зрозуміти! Дивовижно :)
Navaneeth

3
Ідеальний приклад, люблю пояснення
Робін-Худі

104

Вони не виконують однакову роботу: $emitрозсилає подію вгору через ієрархію розмаху, в той час як посилання $broadcastпосилає вниз до всіх областей дитини.


2
Так, я зазначив, що у питанні (можливо, я міг би дати зрозуміти напрямок відправки). Але я також зазначив, що це досить довільне обмеження. Якщо я можу досягти свого «слухача», чому я не можу завжди робити це вниз $rootScope?
Новий Дев

Тому що $-емісія не впливатиме на сферу застосування дитини чи братів та сестер. Вони просто відображають типи розповсюдження подій Javascript - захоплення та барботаж. $ трансляція використовується для захоплення, а $ emit використовується для барботування. Зараз є, здавалося б, стародавня стаття quirksmode, яка досить добре пояснює різницю: quirksmode.org/js/events_order.html
Алан Л.

77

Я зробив наступну графіку з наступного посилання: https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

Область застосування, rootScope, випромінювати, транслювати

Як бачите, $rootScope.$broadcastвражає набагато більше слухачів, ніж $scope.$emit.

Також $scope.$emitефект барботажу можна скасувати, тоді як $rootScope.$broadcastне можна.


24
Я бачу багато стрілок.
Марс Робертсон

4
@MichalStefanow Я фанат візуальних відповідей :)
Maria Ines Parnisari

@mparnisari :. $ Broadcast (ім'я, аргументи) - трансляція події вниз через область $ усіх дітей. $ emit (ім'я, аргументи) - передайте подію в межах ієрархії діапазону $ всім батькам, включаючи $ rootScope
CodeMan

19

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

$ range. $ emit: Цей метод передає подію у напрямку вгору (від дитини до батьків)

введіть тут опис зображення $ obseg. $ Трансляція: метод передає подію у напрямку вниз (від батьків до дитини) до всіх контролерів-дочірніх.

введіть тут опис зображення $ range. $ on: Метод реєструється для прослуховування якоїсь події. Усі контролери, які слухають цю подію, отримують сповіщення про трансляцію або випромінюють, залежно від того, де вони вписуються в ієрархію дитини-батька.

Подія $ emit може бути скасована будь-яким із діапазону $, який слухає подію.

$ On забезпечує метод "stopPropagation". Викликаючи цей метод, подію можна зупинити від подальшого поширення.

Plunker: https://embed.plnkr.co/0Pdrrtj3GEnMp2UpILp4/

У разі застосування діапазонів братів та сестер (сфери, які не перебувають у прямій ієрархії батько-дитина), то $ emit та $ широкомовні передавати не будуть.

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

Докладніші відомості див. На http://yogeshtutorials.blogspot.in/2015/12/event-based-communication-bet between-angularjs-controllers.html


Посилання на рішення вітається, але, будь ласка, переконайтеся, що ваша відповідь корисна без неї: додайте контекст навколо посилання, щоб ваші колеги користувачі мали уявлення про те, що це таке і чому воно є, а потім наведіть найбільш релевантну частину сторінки, яку ви " повторне посилання на випадок, якщо цільова сторінка недоступна. Відповіді, які є трохи більше ніж посилання, можуть бути видалені.
Baum mit Augen

Мета полягала в тому, щоб забезпечити працюючий планкер, однак я тут додав відповідний опис.
Йогеш

3

@Eddie дав ідеальну відповідь на поставлене запитання. Але я хотів би звернути увагу на використання більш ефективного підходу Pub / Sub.

Як свідчить ця відповідь,

$ Мовлення / $ на підході не є надзвичайно ефективним, оскільки він транслює в усіх областях (або в одну сторону, або в обидва напрями ієрархії області). Хоча підхід 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);АБО PubSub.unsubscribe('event-name');.

ПРИМІТКА Не забудьте скасувати підписку, щоб уникнути витоку пам'яті.


2

Використовуйте RxJS в сервісі

Як щодо ситуації, коли у вас є, наприклад, Служба, яка тримає стан. Як я можу підштовхнути зміни до цієї Служби, а інші випадкові компоненти сторінки знають про такі зміни? Останнім часом боролися з вирішенням цієї проблеми

Створіть послугу з розширеннями RxJS для кутових .

<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 .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.