请原谅我后面的代码墙,但每个块只有一个小的更改,并且每个更改都被注释了。
我正在尝试使用 Sidewaffle 模板包附带的 Angular+Typescript“控制器作为”模板。这就是模板开箱即用的样子。我在这里对模板所做的唯一修改是注释、空格和将“app1”重命名为“app”:
interface ItestControllerScope extends ng.IScope {
vm: testController;
}
interface ItestController {
greeting: string;
controllerId: string; //This won't work...
changeGreeting: () => void;
}
class testController implements ItestController {
static controllerId: string = "testController"; //...because this is static.
greeting = "Hello";
constructor(private $scope: ItestControllerScope, private $http: ng.IHttpService, private $resource: ng.resource.IResourceService) {
}
changeGreeting() {
this.greeting = "Bye";
}
}
app.controller(testController.controllerId,
['$scope', '$http', '$resource', ($scope, $http, $resource) =>
new testController($scope, $http, $resource)
]);
首先要注意的是,由于controllerId
控制器类上的静态成员和接口controllerId
所需的成员,它甚至不会编译。Icontroller
由于接口的成员需要在类的类型的实例端实现,所以这是行不通的。
这很烦人,但很容易解决,尽管这样做会丢失一些类型检查:
interface ItestControllerScope extends ng.IScope {
vm: testController;
}
interface ItestController {
greeting: string;
changeGreeting: () => void;
}
class testController implements ItestController {
//we leave the static member on the class and remove the member
//from the interface
static controllerId: string = "testController";
greeting = "Hello";
constructor(private $scope: ItestControllerScope, private $http: ng.IHttpService, private $resource: ng.resource.IResourceService) {
}
changeGreeting() {
this.greeting = "Bye";
}
}
app.controller(testController.controllerId,
['$scope', '$http', '$resource', ($scope, $http, $resource) =>
new testController($scope, $http, $resource)
]);
现在可以编译了,但问题是如何将调用app.controller()
转换为 javascript。不是直接将构造函数传递给app.controller()
,而是封装在一个匿名函数中,我们最终得到的是构造函数中的构造函数:
var testController = (function () {
function testController($scope, $http, $resource) {
this.$scope = $scope;
this.$http = $http;
this.$resource = $resource;
this.greeting = "Hello";
}
testController.prototype.changeGreeting = function () {
this.greeting = "Bye";
};
testController.controllerId = "testController";
return testController;
})();
app.controller(testController.controllerId,
['$scope', '$http', '$resource',
//Why won't this work? Why would we want to do this in the first place?
function ($scope, $http, $resource) {
return new testController($scope, $http, $resource);
}
]);
现在,当我们尝试在视图中使用“controller as”语法时,Angular 找不到别名控制器——视图绑定到一个空对象。
我能说的最好的,Typescript 模板应该是这样的:
interface ItestControllerScope extends ng.IScope {
vm: testController;
}
interface ItestController {
greeting: string;
changeGreeting: () => void;
}
class testController implements ItestController {
static controllerId: string = "testController";
greeting = "Hello";
constructor(private $scope: ItestControllerScope, private $http: ng.IHttpService, private $resource: ng.resource.IResourceService) {
}
changeGreeting() {
this.greeting = "Bye";
}
}
//Now we're passing the controller constructor directly instead of
//wrapping the constructor call in another constructor
app.controller(testController.controllerId,
['$scope', '$http', '$resource',testController]);
编译成这个javascript:
var testController = (function () {
function testController($scope, $http, $resource) {
this.$scope = $scope;
this.$http = $http;
this.$resource = $resource;
this.greeting = "Hello";
}
testController.prototype.changeGreeting = function () {
this.greeting = "Bye";
};
testController.controllerId = "testController";
return testController;
})();
app.controller(testController.controllerId,
['$scope', '$http', '$resource', testController]);
效果很好。所以我有两个主要问题:
- 为什么你会想要将控制器构造函数包装在 lambda 中以交给 Angular 的
controller()
方法,而不是直接交给构造函数? - 为什么模板在一个类上会有一个静态成员,它试图用该类实现的接口上的一个成员来强制执行?
我唯一的猜测是,这两个问题在 Typescript 和 Angular 的早期版本组合中都不是问题,但我不知道,因为我对这两个版本都很陌生。我正在使用 Typescript v1.4 和 Angular v1.3.14