将RequireJS与TypeScript和AngularJS一起使用

Using RequireJS with TypeScript and AngularJS

我将全力以赴,尝试在使用RequireJS时在TypeScript中定义Angular模块。 花费了数天时间试图解决所有问题,却四处寻找解决方案,但无济于事。 请帮助,我很困惑!

我没有使用Visual Studio,而是使用WebStorm。 但是,这并不重要。
我正在使用TS 9.1,AngularJS 1.0.7,RequireJS 2.1.8。
我也尝试过使用DefinitelyTyped的angular.d.td,但这没有帮助。

有没有人为应用程序初始化提供一个TS角度应用程序模块的简单示例,另一个具有控制器的TS角度模块已被RequireJS加载,引用了" DefinitelyTyped / angularjs / angular.d.ts",并调用了'angular.module '定义自己,然后在网页中引用控制器?

请帮忙。...我在TypeScript,RequireJS,AngularJS模块地狱中燃烧。


我能够一起使用这三种技术。我从DefinitelyTyped中添加了angular.d.ts和其他文件到我的Visual Studio项目中,但是我还需要使用declare module语句添加模块声明。这是因为DefinitelyTyped中的角度定义是为无需AMD / requirejs而使用而编写的。也许最好在不使用AMD的情况下使用jquery和angular(使用标签加载它)并且仅将AMD用于应用程序模块,但是无论如何,这是从我的项目中提取的示例:

index.html

1
<script src="webjars/requirejs/2.1.11/require.js" data-main="js/requireMain">

requireMain.ts

requirejs的主文件。它是TypeScript文件,但不使用import语法,而是使用通常的requirejs语法。它还声明了角度模块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
require.config({
    baseUrl: '../js',
    paths: {
        'jquery': '../webjars/jquery/1.11.0/jquery',
        'angular': '../webjars/angularjs/1.2.16/angular',
        'angular-route': '../webjars/angularjs/1.2.16/angular-route',
        'angular-resource': '../webjars/angularjs/1.2.16/angular-resource',
        'angular-ui-bootstrap': '../webjars/angular-ui-bootstrap/0.10.0/ui-bootstrap-tpls',
    },
    shim: {
        'jquery': { exports: 'jquery' },
        'angular': { exports: 'angular', dep: ['jquery'] },
        'angular-route': { exports: 'angular-route', deps: ['angular'] },
        'angular-resource': { exports: 'angular-resource', deps: ['angular'] },
        'angular-ui-bootstrap': { exports: 'angular-ui-bootstrap', deps: ['angular'] },
    },
});

// TypeScript declarations useful for importing angular modules
declare module 'angular' {
    var angular: ng.IAngularStatic;
    export = angular;
}
declare module 'angular-route' {
}
declare module 'angular-resource' {
}
declare module 'angular-ui-bootstrap' {
}

require(['jquery', 'angular', 'angular-route', 'angular-resource', 'angular-ui-bootstrap', 'bootstrap',
    'application', 'routes'],
    function ($: JQueryStatic, angular: ng.IAngularStatic, angularRoute, angularResource, angularUiBootstrap,
        application, routes) {
        $(function () {
            angular.bootstrap(document, ['application']);
        });
    });

应用程序

1
2
3
4
5
6
7
import angular = require('angular');
import angularRoute = require('angular-route');
import angularResource = require('angular-resource');
import angularUiBootstrap = require('angular-ui-bootstrap');

var application = angular.module('application', ['ngRoute', 'ngResource', 'ui.bootstrap']);
export = application

route.ts

1
2
3
4
5
6
7
8
import application = require('application');
import myModule = require('myModule');

application.config(function ($routeProvider) {
    $routeProvider.
        when('/myPage', { controller: myModule.MyPageCtrl, templateUrl: 'partials/myPage.html' }).
        otherwise({ redirectTo: '/myPage' });
});

myModule.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import application = require('application');
import angularUiBootstrap = require('angular-ui-bootstrap');
import myService = require('myService');

export interface MyPageCtrlScope {
    someData: string;
    someAction: () => void;
}

export class MyPageCtrl {

    constructor(public $scope: MyPageCtrlScope, private PersonService: myService.PersonResourceClass, private $modal: ng.ui.bootstrap.IModalService) {

        PersonService.additionalAction({}).$promise.then(
            (person) => {
                this.$scope.someData = person.email;
            });

        $scope.someAction = this.someAction.bind(this);
    }

    someAction() {
        this.$modal.open({
            templateUrl: 'dialog.html'
        }).result.then(
            () => {
                this.$scope.someData = 'something else';
            });
    }

}

myService.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import application = require('application');
import angularResource = require('angular-resource');

export interface Person {
    id?: number;
    email?: string;
}

export interface PersonResource extends Person, ng.resource.IResource<PersonResource> {
}

export interface PersonResourceClass extends ng.resource.IResourceClass<PersonResource> {
    additionalAction(person: Person): PersonResource;
}

application.factory('PersonService', function ($resource: ng.resource.IResourceService, apiUrl: string): PersonResourceClass {
    return <PersonResourceClass> $resource(apiUrl + '/person/:id', { id:"@id" }, {
        'additionalAction': { method: 'POST', url: apiUrl + '/person/:id/additionalAction' },
    });
});


我知道在这种情况下没有塞子,我们在内部使用大型应用程序。公开地,我有一个小样本:https://github.com/basarat/TypeScriptDeepDive,它全部使用了这三个。

为了帮助您调试,我确定RequireJS + Angular存在一些非TS问题。缩小范围的最简单方法是定义以下变量:

1
2
3
declare var angular:any;
declare var define:any;
declare var require:any;

这将使您像使用JavaScript一样直接使用TypeScript,至少对于requirejs / angularjs而言。

然后,您可以解决问题并提取angular / requirejs的类型定义。