angular 模块中的全局通信:事件总线或中介模式/服务 [英] global communication in angular module: event bus or mediator pattern/service

查看:20
本文介绍了angular 模块中的全局通信:事件总线或中介模式/服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

到目前为止,我已经看到了许多问题的解决方案.当然,最简单的方法是将 $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 模块中的全局通信:事件总线或中介模式/服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆