typescript - 在没有 Angular 的情况下理解 TypeScript 和 SystemJS

标签 typescript module systemjs typescript2.0 es6-modules

我最近一直在研究并使用 TypeScript 制作简单的“hello worlds”。我认为有些事情我无法理解,那就是如何将 System.js 与 TypeScript 结合使用。互联网上的每一个教程或演示都是关于 Angular2 的,我还不想涉及 Angular 2。

例如,我有以下项目结构:

RootFolder
| 
| _lib
| ...... ts (where .ts files are)
|
| components (where compiled .js files are)
| libraries
| ......... systemjs (where system.js is)
|
| index.html
| tsconfig.json

我的 tsconfig.json 文件看起来像:

{
  "compileOnSave": true,
  "compilerOptions": {
    "noImplicitAny": true,
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": true,
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "outDir": "./components"
  },
  "exclude": [
    "node_modules",
    "wwwroot"
  ],
  "include": [
    "./_lib/ts/**/*"
  ]
}

TypeScript 编译按预期工作,没有任何问题。我创建了一个名为“Alerter”的简单类,其中包含以下代码:

//alerter.ts
class Alerter {
    showMessage(): void {
        alert("Message displayed.");
    }
}

export default Alerter

还有一个带有以下代码的 app.ts(这是我的“主”应用程序文件):

//app.ts
import Alerter from "./alerter";

console.log("app.js included & executed");

function test() {
    console.log("test called");
    const alt = new Alerter();
    alt.showMessage();
};

在我的 index.html 中,我只想用 System.js 导入这个 app.js,并且只想从控制台调用“测试”函数。但它不起作用。无论我做了什么,我都无法访问该功能。我看到第一行 console.log 正在执行,但是当我尝试从 chrome 控制台调用 test() 时,它是未定义的。

如果我从我的 main.ts 中删除“alerter”类依赖项,一切正常。因为编译后的 app.js 只包含 console.log 调用和函数定义。

这是我在 index.html 中的 System.js 调用

System.config({
    packages: {
        "components": {
            defaultExtension: "js"
        }
    }
});

System.import("components/app");

我现在真的很绝望,我想我应该回到 Jquery 时代。这很简单,但无法使其工作。

最佳答案

我明白这里发生了什么。这与 TypeScript 的正确使用有关 export关键字和 SystemJS。

根据您的描述,您基本上想要使用 SystemJS 导入 JavaScript 文件,类似于仅使用 <script>标记,然后使用其全局定义的函数。

但这意味着您需要了解 TypeScript 如何编译您的文件。 https://www.typescriptlang.org/docs/handbook/modules.html 处的文档说:

In TypeScript, just as in ECMAScript 2015, any file containing a top-level import or export is considered a module.

这就是你正在做的。 app.ts文件有一个 importalerter.ts文件有一个 export声明,所以这些都将被编译为模块。然后从你的tsconfig.json我看到你正在使用 system格式(但是,这里并不重要)。

模块的一个主要好处是它们不会泄漏任何超出其范围的全局对象。所以当你调用System.import("components/app") test()函数仅存在于该模块中。但是您可以导出该函数并在加载模块后调用它:

这意味着您需要先导出函数:

// app.ts
export function test() {
  ...
};

然后 System.import()返回一个由模块导出对象解析的 Promise,因此我们可以调用 test()那里的方法。

System.import("components/app").then(function(m) {
  m.test();
});

这确实如您所愿。

但是,您似乎想要定义 test()全局运作。在这种情况下,您需要在 window 上定义函数全局对象自己:

// app.ts
function test() {
  ...
}
declare const window;
window.test = test;

现在您可以在导入包后随时使用它:

System.import("components/app").then(function(m) {
  test();
});

SystemJS 有多种方法来操作全局对象,但我认为当你导入的包也有需要解决的依赖项时,没有更简单的方法来使用它们(否则看看这个,但这不是你的用途-案例 https://github.com/systemjs/systemjs/blob/master/docs/module-formats.md#exports )。

关于typescript - 在没有 Angular 的情况下理解 TypeScript 和 SystemJS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43116593/

相关文章:

javascript - Angular 组件中的 HTTP post 回调

Typescript 接口(interface)、函数和命名空间都具有相同的名称。哪个正在导出?

powershell - 为什么 Powershell 的 Install-Module 速度如此之慢?

javascript - 如何使 systemjs 模块加载与 .net mvc 一起工作?

typescript - 将 RxJS 与 TypeScript 结合使用

json - 使用 Typescript 在 vue.js 中加载 JSON 文件

javascript - 使用参数执行 Promise.all

c++ - 如何使用 C++ 在 Node 中编辑歌曲元数据?

typescript - 如何使用 SystemJS 模块启动 Typescript 应用程序?

javascript - 如何将 ./[module] 映射到 System.JS 中的/[module]/[module].js?