55

我已经看到人们在他们的代码中的任何地方都这样做:

$rootScope.$broadcast('someEvent', someParameter); 

然后在一些控制器中:

$rootScope.$on('someEvent', function(event, e){ /* implementation here */ });

现在,我想从指令中广播一个事件。在 rootScope 级别广播它是一种好习惯吗?我想在控制器中处理这个事件。我可以使用 $scope 吗,还是我还需要收听 $rootScope ?

4

3 回答 3

80

就我而言,我只想将一个事件从指令广播到视图的控制器,我在其中使用指令。那么使用广播还有意义吗?

我会让指令调用控制器上的方法,该方法在使用指令的 HTML 中指定:

对于使用隔离范围的指令:

<div my-dir ctrl-fn="someCtrlFn(arg1)"></div>

app.directive('myDir', function() {
  return {
    scope: { ctrlFn: '&' },
    link: function(scope, element, attrs) {
       ...
       scope.ctrlFn({arg1: someValue});
    }

对于不使用隔离范围的指令:

<div my-dir ctrl-fn="someCtrlFn(arg1)"></div>

app.directive('myDir', function($parse) {
  return {
    scope: true,  // or no new scope -- i.e., remove this line
    link: function(scope, element, attrs) {
       var invoker = $parse(attrs.ctrlFn);
       ...
       invoker(scope, {arg1: someValue} );
    }
于 2013-04-24T19:31:07.243 回答
13

不使用 $rootScope 通常是个好主意,因为它是全局的,除非你真的知道你在做什么,否则你不应该污染它。我建议你阅读这篇关于服务、指令和控制器之间通信的文章

于 2013-04-24T18:42:00.690 回答
0

这是一个 TypeScript 示例,说明如何从嵌入式指令回调控制器上的方法。需要注意的最重要的一点是,回调的指令参数名称在定义时使用 &,并且在调用该回调时,您不应使用位置参数,而应使用具有目标中参数名称的属性的对象。

在创建应用模块时注册指令:

module MyApp {
    var app: angular.IModule = angular.module("MyApp");
    MyApp.Directives.FileUploader.register(app);
}

注册码如下:

module MyApp.Directives.FileUploader {
  class FileUploaderDirective implements angular.IDirective {
      public restrict: string = "E";
      public templateUrl: string = "/app/Directives/FileUploader/FileUploaderDirective.html";

      //IMPORTANT - Use & to identify this as a method reference
      public scope: any = {
        onFileItemClicked: "&"
      };
      public controller: string = "MyApp.Directives.FileUploader.Controller";
      public controllerAs: string = "controller";
      public bindToController: boolean = true;
      public transclude: boolean = true;
      public replace: boolean = true;
  }

  export function register(app: angular.IModule) {
      app.controller("MyApp.Directives.FileUploader.Controller", Controller);
      app.directive("fileUploader", () => new FileUploaderDirective());
  }
}

指令的控制器看起来像这样

module MyApp.Directives.FileUploader {
    export class Controller {
        public files: string[] = ["One", "Two", "Three"];
        //The callback specified in the view that created this directive instance
        public onFileItemClicked: (fileItem) => void;

        // This is the controller method called from its HTML's ng-click
        public fileItemClicked(fileItem) {
            //IMPORTANT: Don't use comma separated parameters,
            //instead use an object with property names to act as named parameters
            this.onFileItemClicked({
                fileItem: fileItem
            });
        }
    }
}

指令的 HTML 看起来像这样

<ul>
  <li ng-repeat="item in controller.files" ng-click="controller.fileItemClicked (item)">
    {{ item }}
  </li>
</ul>

主视图将具有您的指令的实例,如下所示

<body ng-app="MyApp" ng-controller="MainController as controller">
  <file-uploader on-file-item-clicked="controller.fileItemClicked(fileItem)"/>
</body>

现在你的 MainController 上只需要一个方法

public fileItemClicked(fileItem) {
  alert("Clicked " + fileItem);
}
于 2016-02-01T12:25:32.927 回答