具有发布/订阅

时间:2016-05-05 08:40:43

标签: javascript angularjs angularjs-directive

我想创建一个带角度事件系统的发布/订阅机制。

angular.module("app",[]);

angular.module("app").directive("first", function($rootScope){
        return {
          template: "First Directive",
          link:function(scope,element,attribute){
               $rootScope.$broadcast("OnFirstDirectiveCreated", {
                "message": "I'm first directive"
            });
      }
    }
})

angular.module("app").directive("second", function($rootScope){
        return {
          template: "Second Directive",
          link:function(scope,element,attribute){
            var handler = $rootScope.$on("OnFirstDirectiveCreated", 
                function (event, args) {
                  console.log("First Directive Message: " + args.message);
            });
      }
    }
})

如果我像这样设置HTML文档,控制台中不会显示任何消息:

<div ng-app="app">
  <first></first>
  <second></second>
</div>

如果我先改变第一和第二顺序,请在控制台上输入消息。

<div ng-app="app">
  <second></second>
  <first></first>
</div>

但我需要第一个指令或内部指令。

<div ng-app="app">
  <first></first>
  <second></second>
</div>

<div ng-app="app">
  <first>
      <second></second>
  </first>
</div>

我尝试了$rootScope.$broadcast$rootScope.$emit,但没有结识。

Working DEMO

2 个答案:

答案 0 :(得分:4)

这是绝对正确的角度行为。

在第一个例子中:

<first></first>
<second></second>

Angular为first标记创建一个指令并立即发送事件,但是还没有创建第二个指令。

在第二个例子中:

<first></first>
<second></second>

在这里,您首先订阅一个事件,然后first指令发送一条消息。因此,second指令接受一个事件。

第三个例子:

<first>
   <second></second>
</first>

这种情况以及第一个例子不会起作用。

<强>解决方案: 解决方案之一是在第一个指令中设置超时,以便在创建后立即发送事件。如果未提供$timeoutdelay的第二个参数,则默认行为是在DOM完成呈现后执行该函数:

angular.module("app").directive("first", function($rootScope, $timeout) {
  return {
    template: "First Directive",
    link: function(scope,element,attribute) {
      $timeout(function() {
        $rootScope.$broadcast("OnFirstDirectiveCreated", {
          "message": "I'm first directive"
        })
      });
    }
  }
});

Demo

答案 1 :(得分:1)

这是因为当执行第一个指令的广播时,第二个指令没有准备就绪,因此信号丢失并且不会发生通信。解决问题的一种方法是使用$ interval函数多次发送信号,并在第二个指令准备就绪时停止发送。当然,第二个指令在从第一个指令接收数据时必须回传。 我要去的第二个解决方案是第二个指令通过以与第一个指令中类似的方式使用$ rootScope进行广播来通知第一个指令。

angular.module("app").directive("second", function($rootScope){
    return {
      template: "Second Directive",
      link:function(scope,element,attribute){
        var handler = $rootScope.$on("secondDirective", 
            function (event, args) {
              console.log("First Directive Data: " + args);
        });

        $rootScope.$broadcast("OnChildDirectiveCreated", {
            "message": "I'm second directive",
            "id":      "secondDirective"
        });
      }
    }
 })

和第一个指令:

angular.module("app").directive("first", function($rootScope){
    return {
      template: "First Directive",
      link:function(scope,element,attribute){
           $rootScope.$on("OnChildDirectiveCreated", function(event, args) {
              $rootScope.$broadcast(args.id, someData);
           });
      }
   }
})

由于您正在使用父子结构,因此始终保证在子指令准备就绪时第一个指令就绪。使用此解决方案,您可以使用许多子指令。希望这有帮助!