在 Typescript 中將 angularjs 指令實現為類別
所以在查看了一些 TypeScript 中 AngularJS 指令的範例之後,似乎大多數人都同意在實作它們時使用函數而不是類別。
我更希望將它們作為一個類別,並嘗試按以下方式實現它們:
module directives
{
export class search implements ng.IDirective
{
public restrict: string;
public templateUrl: string;
constructor()
{
this.restrict = 'AE';
this.templateUrl = 'directives/search.html';
}
public link($scope: ng.IScope, element: JQuery, attributes: ng.IAttributes)
{
element.text("Hello world");
}
}
}
現在這個運作良好。然而,我需要有一個帶有一些屬性的獨立作用域,而我一直在努力找出如何將其包含在類本身中。
邏輯推理表明,既然我可以擁有
public restrict: string;
public templateUrl: string;
我應該能夠擁有像這樣的東西:
public scope;
但我不確定這是否正確,也不知道該如何從那裡繼續(例如如何將屬性添加到範圍中)。
有人知道怎麼解這個嗎?(希望,如果可能的話,不用回退到函數)
謝謝,
答案#1
將指令創建為類可能會有問題,因為你仍然需要使用工廠函數來包裝其實例化。例如:
export class SomeDirective implements ng.IDirective {
public link = () => {
}
constructor() {}
}
無效的方法
myModule.directive('someDirective', SomeDirective);
由於指令不是使用 'new' 調用的,而是直接作為工廠函數調用的。這將會對你的構造函數實際返回的內容造成問題。
含有警告的意思是什麼
myModule.directive(() => new SomeDirective());
這在沒有涉及任何 IoC 的情況下運作良好,但一旦你開始引入可注入的項目,你就必須為你的工廠函數和指令構造函數維護重複的參數列表。
export class SomeDirective implements ng.IDirective {
...
constructor(someService: any) {}
}
myModule.directive('someDirective', ['someService', (someService) => new SomeDirective(someService)]);
如果你喜歡,那仍然是一個選擇,但重要的是要了解指令註冊實際上是如何被使用的。
另一種方法
Angular 實際上期望的是一個指令工廠函數,所以應該是像這樣的東西:
export var SomeDirectiveFactory = (someService: any): ng.IDirective => {
return {
link: () => {...}
};
}
SomeDirectiveFactory.$inject = ['someService']; //including $inject annotations
myModule.directive('someDirective', SomeDirectiveFactory);
這樣做的好處是可以使用 $inject 註解,因為在這種情況下 Angular 需要它在工廠函數上。
你也可以總是從工廠函數返回你類的實例:
export var SomeDirectiveFactory = (someService: any): ng.IDirective => {
return new SomeDirective(someService);
}
SomeDirectiveFactory.$inject = ['someService']; //including $inject annotations
但這真的取決於你的使用情況,你能接受多少參數列表的重複,等等。
答案#2
假設你現有的可以在沒有隔離範圍的情況下運作,以下應該可以在隔離範圍下運作:
module directives
{
export class search implements ng.IDirective
{
public restrict = 'AE';
public templateUrl = 'directives/search.html';
public scope = {
foo:'=',
bar:'@',
bas:'&'
};
public link($scope: ng.IScope, element: JQuery, attributes: ng.IAttributes)
{
element.text("Hello world");
}
}
}
