【问题标题】:Using RequireJS with TypeScript and AngularJS将 RequireJS 与 TypeScript 和 AngularJS 一起使用
【发布时间】:2013-08-11 10:37:29
【问题描述】:

我要绞尽脑汁尝试在使用 RequireJS 时在 TypeScript 中定义一个 Angular 模块。一直在寻找解决方案,同时花费数天时间试图弄清楚这一切无济于事。请帮忙,我很困惑!

我使用的不是 Visual Studio,而是 WebStorm。然而,这应该无关紧要。 我正在使用 TS 9.1、AngularJS 1.0.7、RequireJS 2.1.8。 我也尝试过使用 distinctlyTyped 的 angular.d.td,但它没有帮助。

有没有人有一个用于应用程序初始化的 TS Angular 应用程序模块的简单示例,以及另一个具有控制器的 TS Angular 模块,加载 RequireJS,引用“DefinitelyTyped/angularjs/angular.d.ts”,并调用' angular.module' 来定义自己,然后在网页中引用控制器?

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

【问题讨论】:

  • 就我个人而言,我看不到在应用程序内部使用 requirejs 的任何 好处。很快就会对我当前的工作流程进行视频教程。但如果你知道 grunt,你可以看看:github.com/basarat/video-angular-typescript 它使用了npmjs.org/package/grunt-ts
  • 我不使用 Angular,但我使用带有 TypeScript 的 Dojo(它有自己的 RequireJS 版本)。试了几次才弄明白。一些细节有点棘手,特别是因为 TypeScript 默认使用与 RequireJS 不兼容的 CommonJS 样式模块。您可以查看我的github.com/schungx/Dojo-TypeScript 以获得一些灵感。我有一本手册,详细说明了如何在 Dojo 中使用 TypeScript,你应该从那里得到一些想法。

标签: angularjs requirejs typescript


【解决方案1】:

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

index.html

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

requireMain.ts

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

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']);
        });
    });

应用程序.ts

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

routes.ts

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

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

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' },
    });
});

【讨论】:

  • 非常好。谢谢!
  • 谢谢!我真的很喜欢你的解决方案的结构,但我在 application.js 中得到 this error
  • 你有一个包含整个解决方案的 git 存储库吗?
  • @Juancho 很遗憾,没有,我没有使用这些技术的公共项目。
  • 这是一个相对较旧的答案,我认为今天应该可以直接使用角度定义(requireMain.ts 中没有“声明模块”语句)。
【解决方案2】:

据我所知,在这种情况下没有停止器,我们在内部的大型应用程序中使用。公开我有这个小样本:https://github.com/basarat/TypeScriptDeepDive,它使用了所有三个。

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

declare var angular:any;
declare var define:any; 
declare var require:any; 

这将允许您直接使用 TypeScript,就好像它是 javascript,至少对于 requirejs/angularjs。

然后你可以整理你的问题并为 angular / requirejs 引入类型定义。

【讨论】:

    猜你喜欢
    • 2014-02-20
    • 2014-10-06
    • 1970-01-01
    • 2016-06-22
    • 1970-01-01
    • 1970-01-01
    • 2014-10-10
    • 2013-02-14
    • 1970-01-01
    相关资源
    最近更新 更多