无法导入自定义组件 - Angular2 和 TypeScript

Cannot import a custom component - Angular2 and TypeScript

我正在尝试在 app.ts 中导入自定义组件,但出现错误“TS2307:找不到模块 'MyComponent'”我已经看过了,找不到任何对我有帮助的东西。

有些人写道:使用 "moduleResolution":"classic",但如果我这样做,那么我会得到其他所有内容的 TS2307 错误(所有 angular2/ ...) 除了 MyComponent。

其他人写道 "run tsc --declaration MyComponent.ts" - 它确实生成了一个 MyComponent.d.ts 文件(同时在控制台中抛出错误,例如 "Cannot compile unless the --module flag is provided" - 它在 tsconfig 中作为选项提供 - 或 "Cannot find module 'angular2/common'" 对于我在 MyComponent.ts 中导入的任何内容 - 但它确实会生成一个 .d.ts 文件),但是在尝试编译 app.ts 时它仍然会给出相同的 TS2307 错误。我发现没什么用。

这是我的项目结构:

| /app
|     /resources
|         /dev
|             /ts
|                 app.ts
|                 MyComponent.ts
|         /dist
|             /js
|                 app.js          // transcompiled app.ts
|                 MyComponent.js  // transcompiled MyComponent.ts
|             /modules            // files copied from the /node_modules/**/ folders (because node_modules is outside versioning and also outside public root (public root is the /app folder)
|                 es6-shim.js
|                 angular2-polyfills.js
|                 system.src.js
|                 Rx.js
|                 http.dev.js
|                 angular2.dev.js
|     index.html
|
| /node_modules
|     /angular2            // 2.0.0-beta.1
|     /es6-promise         // 3.0.2
|     /es6-shim            // 0.33.3
|     /rxjs                // 5.0.0-beta.0
|     /reflect-metadata    // 0.1.2
|     /systemjs            // 0.19.6
|     /zone.js             // 0.5.10
| 

这是我的tsconfig.json:

{
    "compilerOptions": {
        "target": "ES5",
        "module": "system",
        "moduleResolution": "node",
        "sourceMap": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "removeComments": true,
        "noImplicitAny": false,
        "outDir": "app/resources/dist/js"
    },
    "files": [
        "app/resources/dev/ts/app.ts"
    ]
}

我的app.ts:

import { bootstrap } from "angular2/platform/browser";
import { Component, View } from "angular2/core";
import { HTTP_PROVIDERS, Http, Response } from "angular2/http";

//My Custom Components:
import { MyComponent } from 'MyComponent';

/**
 * APP
 */
@Component({
    selector: 'my-app'
})
@View({
    directives: [MyComponent],
    template: `
        <my-component></my-component>
        plus other html
    `
})
class MyApp {
    public whatever;

    constructor(public http: Http) {
        // initialize this.whatever
    }

    makeRequest(): void {
        this.http.request('/_http/response.json')
            .subscribe((res:Response) => {
                this.whatever = res.json();
            });
    }
}

bootstrap(MyApp, [ HTTP_PROVIDERS ]);

这是我的 MyComponent.ts:

import { Component } from 'angular2/core';
import { NgFor, NgIf } from 'angular2/common';

@Component({
    selector: 'my-component',
    template: `
        <div>MY IMPORTED COMPONENT</div>
    `
})
export class MyComponent {

    constructor() {}

    doSomething(): void {
        console.log('Doing something');
    }
}

我的app.tsMyComponent.ts都在同一个文件夹里。无论如何,我也试过这样的路径:从“/app/resources/dev/ts/MyComponent”导入{MyComponent}。 另外,我已经尝试将它添加到 tsconfig 中的文件数组中(有些人写道我应该这样做)......仍然......没有任何效果!我也检查了 js 输出,因为有些人写即使它抛出错误,它可能仍然被编译......运气不好!

====================

编辑:

好的,正如 inoabrian 在第一条评论中建议的那样...我以为我尝试了所有方法,但似乎我还没有为导入部分尝试过“./MyComponent”。

import { MyComponent } from './MyComponent';

现在转译器开始工作了。谢谢 inoabrian,但现在我有另一个问题。当我在浏览器中尝试 运行 时,我检查了我的控制台并且 systemjs 和 angular2-pollyfills 尖叫:

http://my-app/resources/dist/js/MyComponent 404 (Not Found)

分别是:

XHR error (404 Not Found) loading  http://my-app/resources/dist/js/MyComponent(…)

不要被路径所迷惑(与我的项目文件夹结构相比),当我访问 http://my-app

时,我的本地服务器指向 /app

这是我的 index.html 系统配置和所有包含的 js 文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <!-- ... Meta tags & CSS assets -->

    <script src="resources/dist/modules/es6-shim.js"></script>
    <script src="resources/dist/modules/angular2-polyfills.js"></script>
    <script src="resources/dist/modules/system.src.js"></script>
    <script src="resources/dist/modules/Rx.js"></script>
    <script src="resources/dist/modules/http.dev.js"></script>
    <script src="resources/dist/modules/angular2.dev.js"></script>
</head>
<body>
<script>
    System.config({
        packages: {
            app: {
                format: 'register',
                defaultExtension: 'js'
            }
        }
    });
    System.import('resources/dist/js/app.js')
            .then(null, console.error.bind(console));
</script>

<my-app></my-app>

</body>
</html>

我觉得我应该对转译文件 "MyComponent.js" 再做一件事,但不知道是什么(我已经尝试将它添加到 System.import,希望它会接受一个数组......但它似乎没有)。接下来我该做什么?

P.S. 尽管如此,这还是令人失望,我希望将 MyComponent 导入 app.ts 将是一切,并且我会找到 MyComponent class + 来自 MyComponent.ts 的所有内容 + 我的转译 app.ts 文件全部在一个 app.js 文件中,没有另一个 js 文件:(

有点奇怪的是,您在与 app.js 相同的文件夹中没有 MyComponent.js。在我的例子中,当我在 tsconfig.json 文件中添加 outDir 时,我所有的 TypeScript 文件都被编译成这个文件夹中的 JavaScript。

这是我在 tsconfig.json 文件中的配置:

{
  "compilerOptions": {
    "target": "ES5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "outDir": "app/resources/dist/js"
 },
  "exclude": [
    "node_modules"
  ]
}

我运行编译阶段用命令:tsc -w.

希望对你有帮助, 蒂埃里

我相信您在系统配置中缺少正确的参数。 像这样添加:

System.config({
   defaultJSExtensions: true
})

我知道它早就应该了,但也许其他人可能会从答案中受益。 我确实意识到最终的问题是什么(除了我已经在原始问题中编辑过的内容)。这里是: 我确实提到我有一个自定义文件夹结构并且不愿意更改它。如果我有,它会通过简单地遵循 angular 2 快速入门来工作。但这不会让我意识到我的具体情况下的问题,我也不会理解 System.js 是如何工作的。

问题出在我的 System.config() - 在包部分。 这是错误的代码:

System.config({
    packages: {
        app: {
            format: 'register',
            defaultExtension: 'js'
        }
    }
});
System.import('my/path/to/app_main_file');

我的错误是认为键 "app" 只是一个通用键,来自单词 "application"。事实证明,在 packages 对象中,每个键实际上代表一个路径(该包 - 它是文件 - 在您的应用程序中驻留的位置)。所以,假设我的转译文件所在的文件夹是 "my/app/public" 并且 "app_main_file" 是我的应用程序的主要 js 文件,那么我实际上应该有这样的东西:

System.config({
    packages: {
        'my/app/public': {
            format: 'register',
            defaultExtension: 'js'
        }
    }
});
System.import('my/app/public/app_main_file')
    .then(null, console.error.bind(console));

或者,你可以把配置部分写得更好,像这样:

System.config({
    packages: {
        'my-app': {
            format: 'register',
            defaultExtension: 'js'
        }
    },
    map: {
        'my-app': 'my/app/public'
    }
});

我认为 "map" 的功能和使用方法不言自明。

P.S。我知道在我的回答中我没有遵循与原始问题完全相同的文件夹结构,但我认为这样解释更有意义。如果重要,只需将上面的 "my/app/public" 替换为我最初在问题中的内容:"resources/dist/js/",这是一回事。