12

我正在玩Angular2。作为基础,我使用了angular.io页面中的快速入门项目。

一切似乎都很好,但是一旦我尝试将服务(ItemService)注入我的服务,AppComponent我就会得到以下异常:

Token(ComponentRef) 实例化期间出错!。原始错误:无法解析 AppComponent 的所有参数。确保它们都具有有效的类型或注释。

我在互联网上看到过类似的问题(包括 stackoverflow,例如这篇文章),但似乎都没有解决我的问题。有没有人有任何想法,问题可能是什么?

我还看到了一些解决方案(例如 Angular2 存储库中的解决方案),它们使用Injectable-annotation 装饰可注入类。但是这对我不起作用,因为它没有在angular.d.ts. 我使用了错误的版本吗?

您可以在以下 Plunker 中找到我的解决方案:http: //plnkr.co/edit/7kK1BtcuEHjaspwLTmsg

作为记录,您还可以在下面找到我的两个文件。请注意,app.js来自 Plunker 的是我下面的 TypeScript 文件生成的 JavaScript 文件,例外总是相同的。

index.html

<html>
    <head>
        <title>Testing Angular2</title>
        <script src="https://github.jspm.io/jmcriffey/bower-traceur-runtime@0.0.87/traceur-runtime.js"></script>
        <script src="https://jspm.io/system@0.16.js"></script>
        <script src="https://code.angularjs.org/2.0.0-alpha.23/angular2.dev.js"></script>
    </head>
    <body>
        <app></app>
        <script>
            System.import('js/app');
        </script>
    </body>
</html> 

js/app.ts

/// <reference path="../../typings/angular2/angular2.d.ts" />

import {Component, View, bootstrap, For, If} from "angular2/angular2";

class Item {
    id:number;
    name:string;

    constructor(id:number, name:string) {
        this.id = id;
        this.name = name;
    }
}

class ItemService {
    getItems() {
        return [
            new Item(1, "Bill"),
            new Item(2, "Bob"),
            new Item(3, "Fred")
        ];
    }
}

@Component({
    selector: 'app',
    injectables: [ItemService]
})
@View({
    template: `<h1>Testing Angular2</h1>
               <ul>
                 <li *for="#item of items">
                   {{item.id}}: {{item.name}} |
                   <a href="javascript:void(0);" (click)="toggleSelected(item);">
                     {{selectedItem == item ? "unselect" : "select"}}
                   </a>
                 </li>
               </ul>
               <item-details *if="selectedItem" [item]="selectedItem"></item-details>`,
    directives: [For, If, DetailComponent]
})
class AppComponent {
    items:Item[];
    selectedItem:Item;

    constructor(itemService:ItemService) {
        this.items = itemService.getItems();
    }

    toggleSelected(item) {
        this.selectedItem = this.selectedItem == item ? null : item;
    }
}

@Component({
    selector: 'item-details',
    properties: {
        item: "item"
    }
})
@View({
    template: `<span>You selected {{item.name}}</span>`
})
class DetailComponent {
    item:Item;
}

bootstrap(AppComponent);

提前感谢您的任何想法!

4

3 回答 3

11

检查几件事:-

1) 确保您使用的是从您的软件包位置安装的正确版本的 typescript (1.5.x)。() 如果您安装了以前版本的 typescript,则仅使用“tsc”命令可能会从环境路径指向现有 (< 1.5) 位置。

--emitDecoratorMetadata2) 确保在 tsc 命令中使用flag。这是必要的,因此 javascript 输出会为装饰器创建元数据。

3)Error - Cannot read property 'annotations' of undefined 因为指令具有尚未定义AppComponent的依赖项(当同步函数运行以解决依赖项时)并且TS编译提升变量的方式是未定义的(下面的IIFE尚未运行)。尝试移动before的声明。或者只是将其移动到不同的文件并导入。DetailComponent__decorate(DetailComponentDetailComponentAppComponent

@Component({
    selector: 'item-details',
    properties: {
        item: "item"
    }
})
@View({
    template: `<span>You selected {{item.name}}</span>`
})
class DetailComponent {
    item:Item;
}

@Component({
    selector: 'app',
    injectables: [ItemService]
})
@View({
    template: `<h1>Testing Angular2</h1>
               <ul>
                 <li *for="#item of items">
                   {{item.id}}: {{item.name}} |
                   <a href="#" (click)="toggleSelected(item);">
                     {{selectedItem == item ? "unselect" : "select"}}
                   </a>
                 </li>
               </ul>
               <item-details *if="selectedItem" [item]="selectedItem"></item-details>`,
    directives: [For, If, DetailComponent]
})

class AppComponent {
    items:Item[];
    selectedItem:Item;

    constructor(itemService:ItemService) {
        this.items = itemService.getItems();
    }

    toggleSelected(item) {
        this.selectedItem = this.selectedItem == item ? null : item;
        return false;
    }
}

bootstrap(AppComponent);

编辑

从 angular a26 开始,如果您在遵循当前文档(截至目前)方面遇到问题,请点击此链接,如果它有帮助,因为有一些相关的更改。

于 2015-05-18T19:58:02.717 回答
3

我的设置:我在 Windows 上运行 WebStorm 10.0.2,使用 TypeScript 1.5 beta(编译为 ES5)和 node/npm。

感谢 PSL 的帮助,我发现我的设置存在一些问题。它们与代码无关,例如与类定义的顺序无关等。只是为了记录,我想总结一下我遇到的问题.. PSL 提到了大多数问题,但也许其他人也有同样的问题,例如与 WebStorm 中的编译器有关。

以下是我遇到的问题:

  • 尽管我将 WebStorm 配置为使用通过 npm 安装的 TypeScript 1.5,但还是使用了旧版本 (1.3),因为它也安装在我的系统上(我认为是与 Visual Studio 一起安装的)并在%path%变量中注册

  • 我将 WebStorm 配置为使用 TypeScript 的“自定义编译器版本”(在设置/语言和框架/TypeScript 中),具有以下参数:-emitDecoratorMetadata -m commonjs -t es5 -sourceMap. 这有些不起作用..我不确定它是否与 WebStorm 中的问题有关。没有-emitDecoratorMetadata它编译的标志,但injectables没有工作。

    [2015 年 6 月 9 日更新:是的,它与WebStorm中的一个问题有关]

  • 但是我需要-emitDecoratorMetadata-flag 才能使injectablesAngular2 工作。

  • 我的解决方案是在 WebStorm 中添加一个自定义的“文件观察器”(而不是使用“内置编译器”函数),并带有以下参数:-emitDecoratorMetadata -m commonjs -t es5 --sourceMap $FilePath$

使用 Angular2、TypeScript 1.5 和 WebStorm 的经验教训:

  • 确保 TypeScript 1.5 确实是用于编译 ts 文件的版本(例如在您的 IDE 中)。

  • 确保-emitDecoratorMetadata已指定。

  • 如果类是按特定顺序或在自己的文件中定义的等,这没有什么区别。-> 顺序很重要!将类/组件拆分为不同的文件可以解决问题,并且通常会导致更好的可维护文件。

再次感谢 PSL 的宝贵意见!

于 2015-05-19T16:33:12.157 回答
2

我也遇到过同样的问题。以下是决议:

  1. --emitDecoratorMetadata 在 tsc 中丢失
  2. 如果我从同一个文件注入服务,它就会失败,但是当我把服务放在其他文件时,当导入它时,它就开始工作了。可能是我使用的 Angular2 版本中的错误。
于 2015-08-01T11:06:18.080 回答