我最近一直在研究并使用 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
文件有一个 import
和 alerter.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/