Angularjs $rootScope.$broadcast vs.$scope.$emit

Angularjs $rootScope.$broadcast vs.$scope.$emit,angularjs,angularjs-scope,Angularjs,Angularjs Scope,既然$broadcast和$emit之间的性能差异已经消除,那么有没有理由选择$scope.$emit而不是$rootScope.$broadcast 他们是不同的,是的 $emit仅限于作用域层次结构(向上)-如果它适合您的设计,这可能会很好,但在我看来,这是一个相当随意的限制 $rootScope.$broadcast适用于所有选择收听活动的人,在我看来这是一个更合理的限制 我错过什么了吗 编辑: 为了澄清对答案的回应,派遣的方向不是我想要的问题$scope.$emit向上调度事件,而$sc

既然
$broadcast
$emit
之间的性能差异已经消除,那么有没有理由选择
$scope.$emit
而不是
$rootScope.$broadcast

他们是不同的,是的

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

$rootScope.$broadcast
适用于所有选择收听活动的人,在我看来这是一个更合理的限制

我错过什么了吗

编辑:


为了澄清对答案的回应,派遣的方向不是我想要的问题
$scope.$emit
向上调度事件,而
$scope.$broadcast
-向下调度事件。但是为什么不总是使用
$rootScope.$broadcast
到达所有预期的侦听器呢?

他们做的不是相同的工作:
$emit
通过作用域层次结构向上调度事件,而
$broadcast
向下调度事件到所有子作用域。

tl;太长了,读不下去了(这个TL;DR是从下面的答案)

$emit
向上发送事件
$broadcast
向下发送事件

详细说明

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

$rootScope.$broadcast
是一种让几乎所有人都能听到的方法。这就相当于父母大喊晚餐准备好了,让家里的每个人都能听到

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


$scope.$broadcast
用于
$scope
本身及其子项。这是一个孩子对玩具动物低声耳语,这样他们的父母就听不见了。

@Eddie对这个问题给出了完美的答案。 但我想提请大家注意使用一种更有效的酒吧/酒吧方法

正如答案所示

$broadcast/$on方法效率不高,因为它向所有作用域广播(在作用域层次结构的一个方向或两个方向)。而Pub/Sub方法更直接。只有订阅者才能获得事件,因此它不会进入系统中的每个作用域使其工作

可以使用角度模块。将
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)
publisub.unsubscribe('event-name')


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

我用以下链接制作了以下图形:

正如您所看到的,
$rootScope.$broadcast
$scope.$emit
点击的侦听器多得多

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

在服务中使用RxJS 例如,在您有一个保持状态的服务的情况下呢。如何将更改推送到该服务,以及页面上的其他随机组件如何知道这样的更改?最近一直在努力解决这个问题

使用创建一个服务

然后简单地订阅更改

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
推送更改

这是一个.

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

$scope.$broadcast:Method向下(从父级到子级)将事件分派给所有子控制器

$scope.$on:方法注册以侦听某个事件。正在侦听该事件的所有控制器都会收到广播通知或基于 在子-父层次结构中适合这些对象的位置

$emit事件可以由任何一个侦听该事件的$scope取消

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

普朗克:

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

有关更多详细信息,请参阅

是的,我在问题中提到了这一点(也许我可以明确说明派遣的方向)。但我也注意到,这是一个相当武断的限制。如果我可以访问我的“侦听器”,为什么我不能始终从
$rootScope
向下执行此操作?因为$emit不会影响作用域的子作用域或同级作用域。这些只是映射到javascript的事件传播类型——捕获和冒泡$广播用于捕获,$emit用于冒泡。现在有一篇看似古老的quirksmode文章很好地解释了这一区别:@NewDev原因是页面上经常重复作用域。如果有两个或多个作用域表示不同的数据实例(例如,页面上的患者记录列表,每个都有自己的作用域),则从根广播仅用于其中一个作用域的事件将不起作用。尽可能避免使用
$rootScope
广播可以更好地重用。您所说的没有错,只是一种概括的方法
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();
  };
});