问题描述
到目前为止,我已经看到了许多问题的解决方案.当然,最简单的方法是将 $rootScope
中的一个事件 $emit
作为事件总线,例如( https://github.com/btilford/anti-patterns/blob/master/angular/Angular.md )
So far I have seen many solutions of the problem. The simplest one is, of course, to $emit
an event in $rootScope
as an event bus e.g. ( https://github.com/btilford/anti-patterns/blob/master/angular/Angular.md )
angular.module('myModule').directive('directiveA', function($rootScope) {
return {
link : function($scope, $element) {
$element.on('click', function(event) {
$rootScope.$emit('directiveA:clicked', event);
});
}
}
});
angular.module('myModule').directive('directiveB', function() {
return {
link : function($scope, $element) {
$rootScope.on('directiveA:clicked', function(event) {
console.log('received click event from directiveA');
});
}
}
});
另一个是声明具有中介或发布订阅功能/封闭范围的服务,例如( 多个控制器和指令之间的通信.)
and another one is to declare a service with a mediator or pubsub functionality / an enclosed scope e.g. ( Communicating between a Multiple Controllers and a directive. )
module.factory('MessageService',
function() {
var MessageService = {};
var listeners = {};
var count = 0;
MessageService.registerListener = function(listener) {
listeners[count] = listener;
count++;
return (function(currentCount) {
return function() {
delete listeners[currentCount];
}
})(count);
}
MessageService.broadcastMessage = function(message) {
var keys = Object.keys(listeners);
for (var i = 0; i < keys.length; i++) {
listeners[keys[i]](message);
}
}
return MessageService;
}
);
问题是:
- 在角度应用程序中使用第二个有什么意义吗?
- 以及它们各自的优缺点是什么?
推荐答案
在编写 AngularJS 应用程序时,创建自己的事件发射器实现会适得其反.Angular 已经提供了基于事件的通信所需的所有工具.
Creating your own implementation of event emitter is counter-productive when writing an AngularJS application. Angular already provides all tools needed for event-based communication.
- 在
$rootScope
上使用$emit
可以很好地进行全球服务间通信,并且实际上没有任何缺点. - 在自然范围(绑定到 DOM 的一部分)上使用
$broadcast
可提供视图组件(指令、控制器)之间的范围通信. - 在
$rootScope
上使用$broadcast
将前两点结合在一起(它提供了一个完全全球性的通信平台).这是任何基于 AngularJS 的库基本上都使用的解决方案.
- Using
$emit
on$rootScope
works nicely for global inter-service communication and doesn't really have any drawbacks. - Using
$broadcast
on a natural scope (one that is bound to a part of your DOM) provides scoped communication between view components (directives, controllers). - Using
$broadcast
on$rootScope
brings the two previous points together (it provides a completely global communication platform). This is the solution used basically by any AngularJS-based library out there.
和
- 如果您担心上一个选项中的性能并且您确实想要单独的事件发射器,您可以通过创建一个独立的作用域来轻松创建一个 (
$rootScope.$new(true)
)并在其上使用$broadcast
.(然后,您可以将其包装到服务中并注入到您想要的任何位置.)
- If you're worried about performance in the previous option and you really want your separate event emitter, you can easily create one by creating an isolated scope (
$rootScope.$new(true)
) and using$broadcast
on it. (You can then wrap it into a service and inject it anywhere you want.)
最后一个选项创建一个集成到 Angular 中的成熟事件发射器(您问题中提供的实现至少需要将所有侦听器调用包装在 $apply()
中以正确集成),它可以如果适合特定用例,还可以用于数据更改观察.
The last option creates a full-fledged event emitter integrated into Angular (the implementation provided in your question would at least need to wrap all listener calls in $apply()
to integrate properly) that can be additionally used for data change observation, if that fits a particular use-case.
但是,除非您的应用程序非常庞大,或者您真的很担心事件名称冲突,否则前三个选项应该足够了.
However, unless your application is really humongous, or you're really paranoid about event name collisions, the first three options should suffice just fine.
我不会详细介绍组件之间的其他通信方式.一般来说,当需要使用scope进行数据共享,控制器直接交互,或者通过DOM Node属性进行通信时,你应该知道.
这篇关于angular 模块中的全局通信:事件总线或中介模式/服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!