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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34878830/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:13:37  来源:igfitidea点击:

Cannot import a custom component - Angular2 and TypeScript

typescriptangularsystemjs

提问by MrCroft

I'm trying to import a custom component within my app.ts, but getting the error "TS2307: Cannot find module 'MyComponent'" I've looked it over, couldn't find anything that would help me.

我正在尝试在我的 app.ts 中导入一个自定义组件,但收到错误“ TS2307:找不到模块 'MyComponent'” 我查看了它,找不到任何可以帮助我的东西。

Some people wrote: use "moduleResolution": "classic", but if I do that then I get the TS2307 error for everything else (all angular2/...) except MyComponent.

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

Others wrote "run tsc --declaration MyComponent.ts" - which does generate a MyComponent.d.ts file (while throwing errors in the console, like "Cannot compile unless the --module flag is provided" - which IS provided in tsconfig as an option - or "Cannot find module 'angular2/common'" for whatever I am importing in MyComponent.ts - but it does generate a .d.ts file), but when trying to compile app.ts it still gives the same TS2307 error. Nohting I've found worked.

其他人写了“运行 tsc --declaration MyComponent.ts”——它会生成一个 MyComponent.d.ts 文件(同时在控制台中抛出错误,比如“除非提供 --module 标志,否则无法编译”——这是在 tsconfig 中提供的作为一个选项 - 或“无法找到模块'angular2/common'”对于我在 MyComponent.ts 中导入的任何内容 - 但它确实生成了一个 .d.ts 文件),但是在尝试编译 app.ts 时它仍然给出相同的TS2307 错误。我发现没有工作。

This is my project structure:

这是我的项目结构:

| /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
| 

This is my tsconfig.json:

这是我的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"
    ]
}

My 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 ]);

And here's my MyComponent.ts:

这是我的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');
    }
}

My app.tsand MyComponent.tsare both in the same folder. Anyway, I've also tried path like this: import { MyComponent } from "/app/resources/dev/ts/MyComponent". Also, I've tried adding it to the files array in tsconfig (some people wrote that I should do that)... Still... Nothing worked! I've also checked the js output, because some people wrote that even though it throws the error, it might still be compiled... No luck!

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

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

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

EDIT:

编辑:

Ok, as inoabrian suggests in the first comment... I thought I tried everything, but it seems I haven't tried "./MyComponent" for the import part.

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

import { MyComponent } from './MyComponent';

Now the transcompiler does it's job. Thank you inoabrian, but now I have another issue. When I try running in the browser, I check my console and both systemjs and angular2-pollyfills scream:

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

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

respectively:

分别:

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

Don't be thrown off by the path (when comparing to my project folder structure), I have my local server pointing at /app when I access http://my-app

不要被路径抛弃(与我的项目文件夹结构相比),当我访问http://my-app时,我的本地服务器指向 / app

This is my index.htmlwith system config and all included js files:

这是我的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>

I have the feeling that I should do one more thing with the transcompiled file "MyComponent.js", but don't know what (I've tried to add it to System.import, hoping it would accept an array... but it seems it doesn't). What should I do next?

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

P.S.This is disappointing nevertheless, I hoped that importing MyComponent into app.ts would be everything, and that I would find the MyComponent class + everything from MyComponent.ts + my transcompiled app.ts file ALL IN ONE app.js file, not haveing yet another js file :(

PS这仍然令人失望,我希望将 MyComponent 导入 app.ts 将是一切,并且我会找到 MyComponent 类 + MyComponent.ts 中的所有内容 + 我的转编译 app.ts 文件 ALL IN ONE app.js 文件,没有另一个js文件:(

采纳答案by MrCroft

I know it's long overdue, but perhaps others might benefit from an answer. I did realize what the final problem was (other than what I've already edited in the original question). Here it is: I did mention I had a custom folder structure and wasn't willing to change it. If I had, it would have worked by simply following the angular 2 quickstart. But it wouldn't have made me realize the problem in my specific case and I wouldn't have understood how System.js works.

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

The problem was in my System.config() - in the packages section. This is the bad code:

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

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

My mistake was thinking that the key "app" is simply a generic key, comming from the word "application". It turns out that in the packages object, each key actually represents a path (where does that package - it's files - reside within your application). So, assuming the folder where my transpiled files are would be "my/app/public" and "app_main_file" is the main js file of my application, then I should've actually had something like this:

我的错误是认为键“应用程序”只是一个通用键,来自“应用程序”一词。事实证明,在包对象中,每个键实际上代表一个路径(该包 - 它是文件 - 驻留在您的应用程序中的哪个位置)。因此,假设我的转译文件所在的文件夹是“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));

Or, you can write the config section even nicer, like this:

或者,您可以更好地编写配置部分,如下所示:

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

I think it's pretty self-explanatory what "map" does and how to use it.

我认为“地图”的作用以及如何使用它是不言自明的。

P.S. I know that in my answer I didn't follow the exact same folder structure as in the original question, but I think it makes more sense to explain it like this. If it matters, just replace "my/app/public" above with what I originally had in the question: "resources/dist/js/", and it's the same thing.

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

回答by eesdil

I believe you are missing the proper parameter in system config. add it like this:

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

System.config({
   defaultJSExtensions: true
})

回答by Thierry Templier

What is a bit strange is that you don't have a MyComponent.jswithin the same folder than app.js. In my case, when I add the outDirin the tsconfig.jsonfile, all my TypeScript files are compiled into JavaScript in this folder.

有点奇怪的是,您MyComponent.js在同一个文件夹中没有app.js. 就我而言,当我outDirtsconfig.json文件中添加.

Here is my configuration in my tsconfig.jsonfile:

这是我在我的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"
  ]
}

I run the compilation phase with the command: tsc -w.

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

Hope it helps you, Thierry

希望对你有帮助,蒂埃里