3

I noticed something interesting in the below code. With ':Hero' commented out, the code works fine, but if I uncomment and give hero a type. It breaks - the page won't even render. From what I can see hero is implicitly of type Hero anyway, why cannot I make it explicit.

@Input() hero/*: Hero*/;

To demo this issue, I have a simple project with four files. The above code is at the end of hero-detail.component.ts:

import {Component, Input} from 'angular2/core';
import {Hero} from './hero';
@Component({
  selector: 'my-hero-detail',
  template: `
    <div *ngIf="hero">
      <h2>{{hero.name}} details!</h2>
      <div><label>id: </label>{{hero.id}}</div>
      <div>
        <label>name: </label>
        <input [(ngModel)]="hero.name" placeholder="name"/>
      </div>
    </div>
  `
})
export class HeroDetailComponent {
   @Input() hero/*: Hero*/;
}

hero.ts defines the Hero interface:

export interface Hero {
  id: number;
  name: string;
}

app.component.ts communicates with hero-detail.component.ts:

import {Component} from 'angular2/core';
import {Hero} from './hero';
import {HeroDetailComponent} from './hero-detail.component';
@Component({
  selector: 'my-app',
  template:`
    <h1>{{title}}</h1>
    <h2>My Heroes</h2>
    <ul class="heroes">
      <li *ngFor="#hero of heroes"
        [class.selected]="hero === selectedHero"
        (click)="onSelect(hero)">
        <span class="badge">{{hero.id}}</span> {{hero.name}}
      </li>
    </ul>
    <my-hero-detail [hero]="selectedHero"></my-hero-detail>
  `,
  styles:[`
    .heroes {list-style-type: none; margin-left: 1em; padding: 0; width: 10em;}
    .heroes li { cursor: pointer; position: relative; left: 0; transition: all 0.2s ease; }
    .heroes li:hover {color: #369; background-color: #EEE; left: .2em;}
    .heroes .badge {
      font-size: small;
      color: white;
      padding: 0.1em 0.7em;
      background-color: #369;
      line-height: 1em;
      position: relative;
      left: -1px;
      top: -1px;
    }
    .selected { background-color: #EEE; color: #369; }
  `],
  directives: [HeroDetailComponent]
})
export class AppComponent {
  public title = 'Tour of Heroes';
  public heroes = HEROES;
  public selectedHero: Hero;
  onSelect(hero: Hero) { this.selectedHero = hero; }
}
var HEROES: Hero[] = [
  { "id": 11, "name": "Mr. Nice" },
  { "id": 12, "name": "Narco" },
  { "id": 13, "name": "Bombasto" },
  { "id": 14, "name": "Celeritas" },
  { "id": 15, "name": "Magneta" },
  { "id": 16, "name": "RubberMan" },
  { "id": 17, "name": "Dynama" },
  { "id": 18, "name": "Dr IQ" },
  { "id": 19, "name": "Magma" },
  { "id": 20, "name": "Tornado" }
];

index.html is probably the least relevant to the issue, so here it is - the last file:

<!DOCTYPE html>
<html>
  <head>
    <title>Angular 2 QuickStart</title>
    <!-- bootstrap -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">

    <!-- 1. Load libraries -->
        <script src="https://rawgithub.com/systemjs/systemjs/0.19.6/dist/system.js"></script>
        <script src="https://code.angularjs.org/tools/typescript.js"></script>
        <script src="https://code.angularjs.org/2.0.0-beta.0/angular2-polyfills.js"></script>
        <script src="https://code.angularjs.org/2.0.0-beta.0/Rx.js"></script>
        <script src="https://code.angularjs.org/2.0.0-beta.0/http.dev.js"></script>
        <script src="https://code.angularjs.org/2.0.0-beta.0/angular2.dev.js"></script>

    <!-- 2. Configure SystemJS -->
    <script>
        System.config({
            transpiler: 'typescript', 
            typescriptOptions: {emitDecoratorMetadata: true}, 
            packages: {'app': {defaultExtension: 'ts'}} 
        });
        System.import('app/boot')
            .then(null, console.error.bind(console));
    </script>

  </head>

  <!-- 3. Display the application -->
  <body>
    <my-app>Loading...</my-app>
  </body>

</html>
4

2 回答 2

1

想通了,很有意思。

  1. 一旦我将“导出接口英雄”更改为“导出类英雄”,问题就解决了。否则它会抱怨“意外的令牌导出”。
  2. 但是,如果我事先将 ts 文件转换为 js 文件,问题就会消失。只有在即时进行转译时,问题才会存在。

    packages: {'app': {defaultExtension: 'ts'}} // change 'ts' to 'js'

于 2015-12-31T01:34:58.150 回答
1

这不是错误。类型只存在于编写和编译过程中。在 JavaScript 中,输入装饰器被翻译成类似这样的东西:

__decorate([core_1.Input("title"), 
  __metadata('design:type', Object)
], MyComponent.prototype, "title", void 0);

无论如何,您的编辑器或 Linter 应该警告您这一点。

于 2015-12-28T07:48:50.120 回答