// hero-detail.component.ts
import {Component} 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>
  `,
  inputs: ['hero']
})

export class HeroDetailComponent {
  public hero: Hero;
}
// app.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:[`
    .selected {
      background-color: #CFD8DC !important;
      color: white;
    }
    .heroes {
      margin: 0 0 2em 0;
      list-style-type: none;
      padding: 0;
      width: 10em;
    }
    .heroes li {
      cursor: pointer;
      position: relative;
      left: 0;
      background-color: #EEE;
      margin: .5em;
      padding: .3em 0em;
      height: 1.6em;
      border-radius: 4px;
    }
    .heroes li.selected:hover {
      color: white;
    }
    .heroes li:hover {
      color: #607D8B;
      background-color: #EEE;
      left: .1em;
    }
    .heroes .text {
      position: relative;
      top: -3px;
    }
    .heroes .badge {
      display: inline-block;
      font-size: small;
      color: white;
      padding: 0.8em 0.7em 0em 0.7em;
      background-color: #607D8B;
      line-height: 1em;
      position: relative;
      left: -1px;
      top: -4px;
      height: 1.8em;
      margin-right: .8em;
      border-radius: 4px 0px 0px 4px;
    }
  `],
  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" }
];

// hero.ts
export interface Hero {
  id: number;
  name: string;
}

为了遵守 Single Responsibility Principle ,将显示hero详细信息抽离成为独立的component。
抽离时需要记住几个点:

  1. AppComponent 里抽离html到独立的 HeroDetailComponent ,并替换为<my-hero-detail></my-hero-detail>

  2. AppComponent 需要 import HeroDetailComponent

  3. 两个文件都需要用到 Hero 这个 interface,也抽离为独立文件 hero.ts,并用 export 对外开放接口

  4. 通过 input 为AppComponentHeroDetailComponent 绑定数据, <my-hero-detail [hero]="selectedHero"></my-hero-detail> ,这里的hero是一个绑定数据的目标属性,没有设置这个目标属性会报错

  5. 而后在 HeroDetailComponent 的 component 添加一个 metadata inputs: ['hero']

  6. 至此,父子component间的数据通道打通,不过刷新页面仍看不到效果,也无报错,是因angular忽略了新标签<my-hero-detail></my-hero-detail>。浏览器无法识别的标签和属性angular也无法识别。

  7. AppComponent 添加 directives: [HeroDetailComponent] 来告知angularjs

directives : Array<Type | any[]>

Specifies a list of directives that can be used within a template.


Doyle
844 声望16 粉丝

前端, angular, vue


引用和评论

0 条评论