global communication in angular module: event bus or mediator pattern/service

前端 未结 3 1480
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-04 22:51

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://gi

3条回答
  •  时光取名叫无心
    2020-12-04 23:36

    I would say that broadcasting is an Angular way how to achieve this.

    However your mediator can work, if you pass internal funcion of directive, in example I have used method on scope, but it can be done also with controller method.

    I have used exact same factory as you post.

    angular.module("sharedService", []) 
    .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;
      }
    )
    
    .directive("directiveA", function(MessageService) {
      return {
        link:function(scope) {
          scope.click = function() {
            MessageService.broadcastMessage("broadcasted message");
          };
        },
        template: ''
      }; 
    })
    .directive("directiveB", function(MessageService) {
      return {
        link:function(scope) {        
          scope.callback = function(message) {
            console.log(message);
          };
    
          MessageService.registerListener(scope.callback);
        }
      };
    });
    

    Full example: http://jsbin.com/mobifuketi/1/edit?html,js,console,output

    Just to be complete, I would like to add, that angular also provides more posibilities how can directives communicate.

    Require atribute

    If your directives are connected in hierarchy, then you can use require attribute which let you to access other directives controller. This is ussually best solution for many cases.

    .directive("directiveA", function() {
      return {
        require: "^directiveB",
    
        link: function(scope, element, attrs, directiveCtrl) {
    
          scope.click = function() {
            directiveCtrl.call();
          };
        },
        template: ''
      }; 
    })
    .directive("directiveB", function() {
      return {
        controller :function() {
           this.call = function() {
    
            console.log("method has been called");
          };
        }
      };
    });
    

    Full example: http://jsbin.com/turoxikute/1/edit?html,js,console,output

    Using $watch

    If the functionality deppends on data and not on action, you cen use $watch and react on the changes of given model or model stored in shared service , its not like listener, its basicly checking of change. I have named method changeState() and log "state changed" for everybody see it clear.

    angular.module("sharedService", []) 
    .service("MediatorService", function() {
      this.state = true;
    
      this.changeState = function() {
         this.state = !this.state;
      };
    })
    
    .directive("directiveA", function(MediatorService) {
      return {
        link:function(scope) {
    
          scope.click = function() {
            MediatorService.changeState();
          };
        },
        template: ''
      }; 
    })
    
    .directive("directiveB", function(MediatorService) {
      return {
        link:function(scope) {
            scope.mediator = MediatorService; 
          scope.$watch("mediator.state", function(oldValue, newValue) {
            if (oldValue == newValue) {
              return;
            }  
    
            console.log("state changed");
          });
        }
      };
    });
    

    Full example: http://jsbin.com/darefijeto/1/edit?html,js,console,output

提交回复
热议问题