我见过人们在他们的代码中的任何地方都这样做:
$rootScope.$broadcast('someEvent', someParameter);
然后在某个控制器中:
$rootScope.$on('someEvent', function(event, e){ /* implementation here */ });
现在,我想从一个指令中宣传一个事件。在rootScope级别播放它是一种好习惯吗?我想在控制器中处理这个事件。我可以使用$ scope,还是我还要听$ rootScope?
答案 0 :(得分:78)
就我而言,我只想将一个指令中的事件广播到视图的控制器,我在其中使用该指令。那么使用广播还有意义吗?
我会让指令在控制器上调用一个方法,该方法在使用该指令的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} );
}
答案 1 :(得分:13)
通常不使用$ rootScope作为全局,除非你真的知道自己在做什么,否则不应该污染它。我建议您阅读this article about communication between services, directives and controllers。
答案 2 :(得分:0)
这是一个TypeScript示例,说明如何从嵌入式指令回调控制器上的方法。最值得注意的是,你的回调的指令参数名称使用&amp;在定义时,并且在调用该回调时,您不应该使用位置参数,而是使用具有在目标中具有参数名称的属性的对象。
在创建应用模块时注册指令:
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);
}