AngularJS:来自指令的广播事件
我已经看到人们从他们的代码中的任何地方这样做:
$rootScope.$broadcast('someEvent', someParameter);
然后在一些控制器中:
$rootScope.$on('someEvent', function(event, e){ /* implementation here */ });
现在,我想从一个指令中宣布一个事件。 在rootScope级别播放它是不是很好的做法? 我想在一个控制器中处理这个事件。 我可以使用$ scope,还是需要在$ rootScope上监听?
就我而言,我只是想从指令中广播一个指令给视图的控制器,在这个视图中我使用了这个指令。 那么使用广播还是有意义的吗?
我会让该指令调用控制器上的一个方法,该方法在使用该指令的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 -- ie, remove this line link: function(scope, element, attrs) { var invoker = $parse(attrs.ctrlFn); ... invoker(scope, {arg1: someValue} ); }
通常不要使用$ rootScope,因为它是全局的,除非你真的知道你在做什么,否则你不应该污染它。 我build议你阅读这篇关于服务,指令和控制器之间通信的文章 。
下面是一个TypeScript的例子,介绍如何从embedded的指令callback控制器上的方法。 最重要的是要注意的是,指令的callback参数名称在定义时使用了&,在调用callback函数时,不应该使用位置参数,而应该使用具有目标中参数名称的属性的对象。
在创build应用程序模块时注册指令:
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); }