$ rootScope。$ broadcast与$ scope。$ emit
既然$broadcast
和$emit
之间的性能差异已经被消除了,那么是否有理由select$scope.$emit
to $rootScope.$broadcast
?
他们是不同的,是的。
$emit
只限于作用域层次结构(向上) – 如果它符合你的devise,这可能是好的,但在我看来,这是一个相当随意的限制。
$rootScope.$broadcast
适用于所有select收听该事件,这在我看来是一个更明智的限制。
我错过了什么吗?
编辑:
为了澄清回答,调度的方向不是我所追求的问题。 $scope.$emit
向上发送事件, $scope.$broadcast
– 向下。 但为什么不总是使用$rootScope.$broadcast
来达到所有预期的监听器呢?
tl; dr (这个tl; dr来自@ sp00m的答案)
$emit
发送一个事件向上…$broadcast
向下发送一个事件
详细的解释
$rootScope.$emit
只允许其他$rootScope
侦听器捕获它。 当你不希望每个$scope
都能得到时,这是很好的。 主要是高层次的沟通。 想想大人们在一个房间里互相交谈,孩子们听不到他们的声音。
$rootScope.$broadcast
是一种让所有东西都能听到的方法。 这就相当于家长大吼大叫晚饭已经准备好了,所以家里的每个人都听到了。
$scope.$emit
是当你想要$scope
和它的所有父母和$rootScope
来听到事件。 这是一个在家里抱怨父母的孩子(但不是在其他孩子可以听到的杂货店里)。
$scope.$broadcast
是用于$scope
本身及其子节点的。 这是一个小孩耳语,所以他们的父母听不到。
他们没有做同样的工作: $emit
通过作用域层次向上调度一个事件,而$broadcast
向下调度一个事件到所有的子作用域。
我从以下链接中提取了以下graphics: https : //toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribeing/
正如你所看到的, $rootScope.$broadcast
比$scope.$emit
有更多的监听器。
另外, $scope.$emit
的冒泡效果可以被取消,而$rootScope.$broadcast
不能。
$ scope。$ emit:这个方法向上调度事件(从child到parent)
$ scope。$ broadcast:方法将事件向下(从父到子)分派给所有子控制器。
$ scope。$ on:方法寄存器来监听某个事件。 所有正在监听该事件的控制器都将获得广播的通知,或者根据父子层次中适合的地方发出广播通知。
$ emit事件可以被正在监听事件的$ scope中的任何一个取消。
$ on提供了“stopPropagation”方法。 通过调用此方法,可以停止事件进一步传播。
Plunker: https ://embed.plnkr.co/0Pdrrtj3GEnMp2UpILp4/
在兄弟范围的情况下(范围不在直接的父子层次结构中),那么$ emit和$ broadcast将不会传递给兄弟范围。
有关更多详细信息,请参阅http://yogeshtutorials.blogspot.in/2015/12/event-based-communication-between-angularjs-controllers.html
艾迪给出了这个问题的完美答案。 但我想提请注意使用Pub / Sub的更有效的方法。
正如这个答案所示,
$ broadcast / $ on方法并不是非常有效,因为它向所有范围进行广播(既可以在一个方向上,也可以在两个方向上进行)。 而Pub / Sub方法更直接。 只有订阅者才能获取事件,因此系统中的所有范围都无法使其工作。
您可以使用angular-PubSub
angular度模块。 一旦将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');
。
注意不要忘记取消订阅以避免内存泄漏。
在服务中使用RxJS
如果你有一个服务,例如持有状态的情况下。 我怎样才能将更改推送到该服务,并在页面上的其他随机组件意识到这样的变化? 近来一直在努力解决这个问题
使用RxJS Extensions for Angular构build服务。
<script src="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上的演示 。