【问题标题】:$emit or $broadcast events from service and listen them in a controller (or several)来自服务的 $emit 或 $broadcast 事件并在控制器(或多个)中监听它们
【发布时间】:2014-04-11 13:23:41
【问题描述】:

我编写了一个简单的示例,我想从服务发出/广播一个事件,我希望控制器监听该事件并更改 UI,但我无法使其工作并调试它的代码似乎停止在侦听器中,但它不执行该函数。

http://plnkr.co/edit/eglcq7zELLfKp86DYzOe?p=preview

服务:

angular.module('ServiceModule', []).
service('servicetest', ['$rootScope', function($rootScope){
    this.test = function(){
      $rootScope.$emit('testevent');
    };
}]);

控制器

angular.module('ControllerModule', ['ServiceModule']).
    controller('ControllerTest', ['$scope','$rootScope','servicetest', function($scope, $rootScope, servicetest){
      $scope.name = 'World';
      servicetest.test();
      $rootScope.$on('testevent', function(){
        $scope.name = 'Joe';
      });
    }]);

索引

<!DOCTYPE html>
<html ng-app="ControllerModule">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.2.x" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" data-semver="1.2.16"></script>
    <script src="controller.js"></script>
    <script src="service.js"></script>
  </head>

  <body ng-controller="ControllerTest">
    <p>Hello {{name}}!</p>
  </body>

</html>

解决方案:

正如 ivarni 或 Walter 品牌所报告的,对触发事件的服务函数的调用必须放在侦听器之后,否则您触发的事件还没有侦听器能够侦听。

我们只需要改变控制器如下:

服务

angular.module('ControllerModule', ['ServiceModule']).
        controller('ControllerTest', ['$scope','$rootScope','servicetest', function($scope, $rootScope, servicetest){
          $scope.name = 'World';
          $rootScope.$on('testevent', function(){
            $scope.name = 'Joe';
          });
          servicetest.test();
        }]);

【问题讨论】:

    标签: javascript angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    您在附加侦听器之前触发了事件。

    试试这个:

      $rootScope.$on('testevent', function(){
        $scope.name = 'Joe';
      });
      servicetest.test();
    

    【讨论】:

    • 对!!谢谢,实际上我不知道这一点,我对AngularJS很陌生。除了官方网站,你知道有什么资源可以解释范围、事件、应用、观看等所有这些事情吗?
    • 嗨@JoeLewis,我推荐ng-book.com。这是一项很小的投资,但非常值得。为您节省大量搜索时间
    【解决方案2】:

    只需将 servicetest.test() 放在控制器中的侦听器下方,如下所示:

      $rootScope.$on('testevent', function(){
        $scope.name = 'Joe';
      });
      servicetest.test();
    

    你在调用 test() 之后附加了监听器,然后就错过了事件。

    【讨论】:

      【解决方案3】:

      我发现在中型应用程序中效果最好的解决方案是围绕 $emit 函数创建一个包装器,并将 $emit 延迟几毫秒,刚好足以注册所有事件。

      您还可以在包装器中引入更多好东西,例如将您当前的 $scope 传递给它,或者让它创建一个新的 $rootscope 子范围(它只是下面的一层,因此在传播时它仍然会很快最高 $rootScope),并将其用作数据通道、作用域消亡后的事件销毁等...

      这是完整的源代码:http://jsfiddle.net/gabrielcatalin/2uRr7

      这里有一段摘录:

      /**
       * Waits a given amount of time before calling emitting
       * This works well when the event registration happens before emitting.
       *
       * @param name
       * @param fn
       * @param wait
       */
      this.delayEmit = function (name, fn, wait) {
          // Because of the $scope's lifecycle the $emit(publish) happens after the $on(subscription)
          //  therefore that needs to be taken care of with a delay
          $timeout(function () {
              self.emit(name, fn);
          }, wait || 100);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        • 2015-02-28
        • 2012-08-22
        • 1970-01-01
        • 2012-02-15
        相关资源
        最近更新 更多