既然$broadcast
和$emit
之间的效果差异已经消除,是否有理由倾向于$scope.$emit
到$rootScope.$broadcast
?
他们是不同的,是的。
$emit
仅限于范围层次结构(向上) - 如果它符合您的设计,这可能是好的,但在我看来这是一个相当随意的限制。
$rootScope.$broadcast
适用于所有选择来听取事件,这在我看来是一个更明智的限制。
我错过了什么吗?
修改
为了澄清答案,发送的方向不是我之后的问题。 $scope.$emit
向上发送事件,$scope.$broadcast
- 向下发送。但为什么不总是使用$rootScope.$broadcast
来覆盖所有预期的听众呢?
答案 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/
正如您所看到的,$rootScope.$broadcast
比$scope.$emit
听到的听众多得多。
此外,$scope.$emit
的冒泡效果可以取消,而$rootScope.$broadcast
则不能。
答案 3 :(得分:18)
$ scope。$ emit:此方法向上调度事件(从子节点到父节点)
$ scope。$ broadcast:方法向下调度事件(从父节点到子节点)到所有子控制器。
$ scope。$ on:用于监听某些事件的方法寄存器。所有正在收听该事件的控制器都会收到广播通知或基于发出的发射 那些适合子 - 父级层次结构的地方。
$ emit事件可以被正在收听事件的$ scope取消。
$ on提供" stopPropagation"方法。通过调用此方法,可以阻止事件进一步传播。
Plunker:https://embed.plnkr.co/0Pdrrtj3GEnMp2UpILp4/
如果是兄弟范围(范围不在直接的父子层次结构中),则$ emit和$ broadcast将不会与兄弟范围进行通信。
答案 4 :(得分:3)
正如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 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
推送更改。