将 Angular 1.x 与 TypeScript 1.5 和 SystemJS 一起使用

Posted

技术标签:

【中文标题】将 Angular 1.x 与 TypeScript 1.5 和 SystemJS 一起使用【英文标题】:Using Angular 1.x with TypeScript 1.5 and SystemJS 【发布时间】:2015-11-27 00:05:20 【问题描述】:

我正在尝试将 Angular 1.x 与 TypeScript 1.5.3 和 SystemJS 一起使用。 index.html 页面设置为 System.import('bootstrapper') 应该可以启动。

bootstrapper.ts 被编译为 bootstrapper.js 并且只要它不使用 angular 就可以正常工作(即只使用 console.log() 可以正常工作)

现在,我想导入并使用 angular 来引导它。我已经完成了jspm install angular 并且我还使用tsd 安装了一些角度类型。类型在bootstrap.ts 文件的顶部引用。

不幸的是,import angular from 'angular' 无法编译,我得到了Module "angular" has no default export。我的问题是:

    为什么import angular from 'angular' 不编译?查看angular.d.ts 文件,我看到declare module 'angular' export = angular; ,如果我理解正确,它是从变量的模块角度的默认导出(在上面的类型文件中定义)declare var angular: angular.IAngularStatic 我注意到执行import 'angular' 编译,然后我实际上可以引用angular 并执行例如angular.module(...),但我认为我没有正确理解它是如何工作的。 import 'angular' 不应该做一个“裸导入”,即只为了它的副作用而运行一个模块吗?如果是这样,那是否意味着这个导入实际上在全局范围内注册了angular

我很确定我没有正确理解模块/类型定义文件在 Typescript 中的工作方式,提前感谢您的解释。

【问题讨论】:

【参考方案1】:

首先,以下是我将 AngularJS 1.5 与 TypeScript 和 SystemJS 一起使用的首选方式:

index.html

<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>

<script>
  SystemJS.import('app')
    .then(function (app) 
      app.bootstrap(document);
    )
    .catch(function (reason)  
      console.error(reason);
    );
</script>

app/main.ts

import angular from 'angular';

const app = angular.module('app', []);

export function bootstrap(target: Element | Document) 
  angular.bootstrap(target, [app.name],  strictDi: true );

tsconfig.json


    "compilerOptions": 
      "module": "system",
      "allowSyntheticDefaultImports": true,
      ....
    

config.js(加载器配置,简化)

SystemJS.config(
  transpiler: "typescript",
  packages: 
    "app": 
      "main": "main.ts",
      "defaultExtension": "ts",
      "meta": 
        "*.ts": 
          "loader": "typescript"
        
      
    
  
);

注意事项:

    如果您使用 JSPM 0.17,请为加载器和转译器指定 "plugin-typescript",而不是 "typescript",或者只运行 $ jspm init 并选择转译器。 您可以默认导入 Angular,但它仍会在全局范围内注册自己。 出现语法错误的原因是angular,其angular.d.ts 声明文件包含CommonJS 样式export = 声明,以允许基于模块和全局命名空间的使用。 SystemJS 为了获得最大的兼容性,会在运行时将其插入到默认导出中。 TypeScript 编译器需要意识到这一点。这可以通过设置"module": "system" 和/或指定"allowSyntheticDefaultImports": true 来完成。为了阐述和明确,我已经这样做了。

    如果你不使用 jspm,你只需要告诉系统 JS 在哪里使用 map 或 package config 找到 typescript

    SystemJS.config(
      map: 
        "typescript": "node_modules/typescript"
      
    );
    

【讨论】:

【参考方案2】:

[...] 如果我理解正确,是模块的默认导出 变量的角度

不,这不是正在发生的事情。如果有意义的话,Angular 会将整个命名空间导出为导出。

import angular from 'angular' 正在尝试从模块中导入 default

您想要的是import * as angular from 'angular';,它将整个导出作为变量导入。

【讨论】:

请注意,import angular 不会尝试导入名为 angular 的内容,它会尝试将名为 default 的内容导入名为 angular 的绑定中。 @loganfsmyth 谢谢,把它和大括号搞混了,谢谢 不知道我明白了。您是说在export = angularangular 指的是d.ts 文件中下一个定义为define module angular 的模块,而不是上面声明为declare var angular: angular.IAngularStatic 的变量?或者它是指变量,但变量是接口类型,它以某种方式将该接口导出为命名空间?如果是这种情况,那么我猜declare var x 实际上并没有创建变量,它只是module.interface 的别名? declare var x 确实创建/声明了变量,但该变量未在模块中导出。导出的变量看起来像 export declare var x;export = x: x ;。当设置--module 标志时,声明的angular 变量仅存在于模块的范围内。当--module 标志未设置时,声明的angular 变量存在于全局范围内。 好吧,因为没有export,所以没有直接导出变量是有道理的。那么export = angular 中的angular 指的是什么?这个模块局部变量?或者下面声明为declare module angular的模块?

以上是关于将 Angular 1.x 与 TypeScript 1.5 和 SystemJS 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

Angular 1.x 与 TypeScript 2.x、@types 和 SystemJS - 使用全局类型

Angular 2 学习笔记

如何在 Angular 1.x 中使用多个根元素

typeScrip 类

如何从 Angular2(Typescript)中的 Json 数组中获取值的总和

typeScrip泛型