$ rootScope。$ broadcast与$ scope。$ emit


349

现在,之间的性能差异$broadcast$emit已被淘汰,没有任何理由,更喜欢$scope.$emit$rootScope.$broadcast

他们是不同的,是的。

$emit 仅限于范围层次结构(向上)-如果适合您的设计,这可能很好,但是在我看来,这是一个相当随意的限制。

$rootScope.$broadcast在所有选择收听此活动的人中都有效,这在我看来是一个更明智的限制。

我想念什么吗?

编辑:

为了对回答做出澄清,调度的方向不是我要解决的问题。$scope.$emit向上调度事件,$scope.$broadcast-向下调度事件。但是,为什么不总是使用它$rootScope.$broadcast来吸引所有预期的听众呢?


Answers:


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
您使用的示例很棒!
阿萨夫2015年

72
哇!即使是孩子也可以理解!令人惊叹的:)
纳瓦内斯2015年

3
完美的例子,喜欢这个解释
Robin-Hoodie 2015年

104

他们做的工作不同:在范围层次结构中向上$emit分发事件,而在所有子范围中向下分发事件。$broadcast


2
是的,我在问题中指出(也许我可以明确说明派遣的方向)。但我也指出,这是一个相当随意的限制。如果我可以联系到“听众”,为什么我不能总是从头开始向下做$rootScope呢?
2014年

因为$ emit不会影响作用域的子作用域或同级作用域。这些只是映射到javascript的事件传播类型-捕获和冒泡。$ broadcast用于捕获,$ emit用于冒泡。现在有一篇看似古老的quirksmode文章很好地解释了这一区别:quirksmode.org/js/events_order.html
Alan L.

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(name,args)-通过所有孩子的$ scope向下广播事件。$ emit(name,args)-向上$ scope层次结构向所有父母发出事件,包括$ rootScope
CodeMan

19

在此处输入图片说明

$ scope。$ emit:此方法向上调度事件(从子级到父级)

在此处输入图片说明 $ scope。$ broadcast:方法将事件向下(从父级到子级)调度到所有子级控制器。

在此处输入图片说明 $ scope。$ on:方法注册以侦听某些事件。所有正在监听该事件的控制器都将根据子父层次结构中适合的位置获得广播通知或发出通知。

监听事件的任何$ scope都可以取消$ emit事件。

$ on提供“ stopPropagation”方法。通过调用此方法,可以阻止事件进一步传播。

柱塞:https ://embed.plnkr.co/0Pdrrtj3GEnMp2UpILp4/

如果是同级作用域(不在直接父子层次结构中的作用域),则$ emit和$ broadcast将不会与同级作用域通信。

在此处输入图片说明

有关更多详细信息,请参阅 http://yogeshtutorials.blogspot.in/2015/12/event-based-communication-between-angularjs-controllers.html


欢迎使用指向解决方案的链接,但是请确保没有该链接的情况下,您的回答是有用的:在链接周围添加上下文,以便您的其他用户可以了解它的含义和含义,然后引用您所使用页面中最相关的部分如果目标页面不可用,请重新链接。只是链接的答案可能会被删除。
Baum mit Augen

目的是提供工作中的活塞,但是,我在此处添加了适当的描述。
Yogesh

3

@Eddie已完美回答了所提问题。但我想提请注意使用更高效的Pub / Sub方法。

正如这个答案所暗示的,

$ broadcast / $ on方法并不是非常有效,因为它广播到所有范围(在范围层次结构的一个方向或两个方向)。尽管发布/订阅方法更为直接。只有订阅者才能获得事件,因此并不能在系统中的每个作用域中都可以使用它。

您可以使用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);ORPubSub.unsubscribe('event-name');

注意请不要忘记取消订阅以避免内存泄漏。


2

在服务中使用RxJS

例如,在您的服务处于保持状态的情况下该怎么办?如何将更改推送到该服务,页面上的其他随机组件会意识到这种更改?最近一直在努力解决这个问题

使用RxJS Extensions for 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

上PLNKR DEMO

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.