$ rootScope。$ broadcast vs. $ scope。$ emit

时间:2014-11-05 07:48:31

标签: angularjs angularjs-scope

既然$broadcast$emit之间的效果差异已经消除,是否有理由倾向于$scope.$emit$rootScope.$broadcast

他们是不同的,是的。

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

$rootScope.$broadcast适用于所有选择来听取事件,这在我看来是一个更明智的限制。

我错过了什么吗?

修改

为了澄清答案,发送的方向不是我之后的问题。 $scope.$emit向上发送事件,$scope.$broadcast - 向下发送。但为什么不总是使用$rootScope.$broadcast来覆盖所有预期的听众呢?

6 个答案:

答案 0 :(得分:1132)

tl; dr (此tl; dr来自@sp00m的答案)

  

$emit向上发送一个事件...... $broadcast向下发送一个事件

详细说明

$rootScope.$emit只允许其他$rootScope侦听器捕获它。当你不希望每个$scope得到它时,这很好。主要是高级别的沟通。把它想象成大人在一个房间里互相交谈,这样孩子们就听不到了。

$rootScope.$broadcast是一种可以让所有内容听到它的方法。这相当于父母大喊大叫,晚餐准备就绪,所以房子里的每个人都听到了。

$scope.$emit是您希望$scope及其所有父母和$rootScope听到此事件的时间。这是一个孩子在家里向父母抱怨(但不是在其他孩子可以听到的杂货店)。

$scope.$broadcast适用于$scope本身及其子女。这是一个孩子对它的毛绒动物说悄悄话,所以他们的父母听不到。

答案 1 :(得分:103)

他们没有做同样的工作:$emit通过范围层次结构调度向上事件,而$broadcast调度事件向下到所有儿童范围。

答案 2 :(得分:76)

我通过以下链接制作了以下图片:https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

Scope, rootScope, emit, broadcast

正如您所看到的,$rootScope.$broadcast$scope.$emit听到的听众多得多。

此外,$scope.$emit的冒泡效果可以取消,而$rootScope.$broadcast则不能。

答案 3 :(得分:18)

enter image description here

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

enter image description here $ scope。$ broadcast:方法向下调度事件(从父节点到子节点)到所有子控制器。

enter image description here $ scope。$ on:用于监听某些事件的方法寄存器。所有正在收听该事件的控制器都会收到广播通知或基于发出的发射 那些适合子 - 父级层次结构的地方。

$ emit事件可以被正在收听事件的$ scope取消。

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

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

如果是兄弟范围(范围不在直接的父子层次结构中),则$ emit和$ broadcast将不会与兄弟范围进行通信。

enter image description here

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

答案 4 :(得分:3)

@Eddie对所提出的问题给出了完美答案。 但我想提请注意使用更有效的Pub / Sub方法。

正如this回答所示,

  

$ 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);PubSub.unsubscribe('event-name');

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

答案 5 :(得分: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推送更改。

DEMO on PLNKR