3

请原谅我后面的代码墙,但每个块只有一个小的更改,并且每个更改都被注释了。

我正在尝试使用 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]);

效果很好。所以我有两个主要问题:

  1. 为什么你会想要将控制器构造函数包装在 lambda 中以交给 Angular 的controller()方法,而不是直接交给构造函数?
  2. 为什么模板在一个类上会有一个静态成员,它试图用该类实现的接口上的一个成员来强制执行?

我唯一的猜测是,这两个问题在 Typescript 和 Angular 的早期版本组合中都不是问题,但我不知道,因为我对这两个版本都很陌生。我正在使用 Typescript v1.4 和 Angular v1.3.14

4

2 回答 2

1

为什么你会想要将控制器构造函数包装在 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
于 2015-03-04T22:26:01.457 回答
1

查看Github 上的源代码可以发现,有问题的模板已经“更新为兼容 Typescript 1.0 和 Angular 1.3”,因此结合以前版本的 Angular 和 Typescript,模板中的所有内容都必须在某些情况下工作过去的时间。

我遇到的两个问题在更新的文件中得到了解决,这些更改与我为使事情运行所做的更改相似。Sidewaffle 模板包尚未相应更新。

更新:在撰写本文时,最新版本的 Sidewaffle 模板包括固定模板。

于 2015-03-04T22:40:07.800 回答