请原谅下面的代码墙,但每个块只有一个小的更改,每个更改都有注释。
我正在尝试使用Sidewaff模板包附带的Angular+Typescript"controller as"模板。这就是模板开箱即用的样子。我在这里对模板所做的唯一修改是注释、空白以及将"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
成员和Icontroller
接口所需的controllerId
成员,它甚至不会编译。由于接口的成员需要在类类型的实例端实现,所以这是行不通的。
这很烦人,但很容易绕过,尽管这样做会丢失一些类型检查:
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
为什么要将控制器构造函数封装在lambda中,然后交给Angular的controller()方法,而不是直接交给构造函数?
你不会的。我没有https://www.youtube.com/watch?v=WdtVn_8K17E
为什么模板在一个类上有一个静态成员,它试图用该类实现的接口上的成员强制执行该成员
关于controllerId: string; //This won't work...
在接口上拥有一个成员并用类实现该接口意味着该类的实例将拥有该成员。然而,您想说的是类中有此成员。这不能通过实现接口来实现。
您可以通过其他方式确保这一点:
var mustHaveId:{controllerId:string};
class Fail{}
class Pass{static controllerId = "Pass"}
mustHaveId = Fail; // Error
mustHaveId = Pass; // Pass
查看Github上的源代码发现,有问题的模板已经"更新为兼容Typescript 1.0和Angular 1.3",因此Angular和Typescript的早期版本的一些组合,模板中的所有内容都必须在过去的某个时候起作用。
我遇到的两个问题在更新后的文件中得到了解决,这些更改与我为使事情正常运行所做的更改类似。Sidewaffle模板包还没有相应更新。
更新:截至本文撰写之时,Sidewaffle模板的最新版本包括固定模板。