【问题标题】:why does giving @Input a type breaks the code?为什么给@Input 一个类型会破坏代码?
【发布时间】:2015-12-28 03:54:08
【问题描述】:

我在下面的代码中发现了一些有趣的东西。注释掉 ':Hero' 后,代码可以正常工作,但如果我取消注释并给 hero 一个类型。它打破了 - 页面甚至不会呈现。从我所看到的 hero 无论如何都是隐含的 Hero 类型,为什么我不能明确表示。

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

为了演示这个问题,我有一个包含四个文件的简单项目。以上代码在 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 定义了 Hero 接口:

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

app.component.ts 与 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 可能与问题最不相关,所以这里是 - 最后一个文件:

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

【问题讨论】:

  • 控制台日志中抛出了什么异常?
  • @drewmoore,谢谢!最后我想通了。如果我随时离开 transpile,我必须将导出接口更改为导出类。我不确定这是否是预期的行为,但至少通过使用导出类,它解决了我的问题。如果我事先转译 ts 文件,则不存在同样的问题。

标签: angular angular2-template


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    想出来了,很有趣。

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

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

    【讨论】:

      猜你喜欢
      • 2020-02-10
      • 2018-02-08
      • 2021-08-15
      • 1970-01-01
      • 2012-10-08
      • 1970-01-01
      • 1970-01-01
      • 2016-01-19
      • 1970-01-01
      相关资源
      最近更新 更多