此刻,HeroesComponent显示英雄列表和所选英雄的详细信息。
随着应用程序的增长保持一个组件中的所有功能将不可维护。您需要将大型组件分成更小的子组件,每个组件都专注于特定的任务或工作流程。
在此页面中,您将通过将英雄详细信息移动到单独的可重复使用的位置来朝此方向迈出第一步HeroDetailsComponent。
该HeroesComponent会目前唯一的英雄名单。该HeroDetailsComponent会提出一个选择英雄的细节。
9.X-使HeroDetailComponent
使用Angular CLI生成一个名为的新组件hero-detail(组件一般在app目录下生产)。
ng generate component hero-detail
该命令脚手架HeroDetailComponent文件并声明组件AppModule。

每次创建组件,都会声明到app.module.ts
9.1-编写模板
从HeroesComponent模板底部剪下英雄细节的HTML ,并将其粘贴到模板中生成的样板上HeroDetailComponent。
粘贴的HTML指的是一个selectedHero。新的HeroDetailComponent可以呈现任何英雄,而不仅仅是一个选定的英雄。因此,在模板中的任何地方都将“selectedHero”替换为“hero”。
完成后,HeroDetailComponent模板应该如下所示:
herodetail.component.html
<div *ngIf="hero"> <h2>{{ hero.name | uppercase }} Details</h2> <div><span>id: </span>{{hero.id}}</div> <div> <label>name: <input [(ngModel)]="hero.name" placeholder="name"/> </label> </div> </div>
9.2-添加英雄属性@Input()
该HeroDetailComponent模板绑定到组件的hero属性,它是类型Hero。
打开HeroDetailComponent类文件并导入Hero符号。
src / app / hero-detail / hero-detail.component.ts(导入英雄)
import { Hero } from ‘../hero‘;
该hero属性 必须是一个Input属性,用装饰器注释,因为外部将像这样绑定到它。@Input() HeroesComponent
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
修改@angular/core进口声明以包含Input符号。
src / app / hero-detail / hero-detail.component.ts(导入输入)
import { Component, OnInit, Input } from ‘@angular/core‘;
添加一个hero属性,在装饰器之前。@Input()
@Input() hero: Hero;
这是你应该对HeroDetailComponent班上唯一的改变。没有更多的属性。没有表示逻辑。该组件仅通过其hero属性接收英雄对象并显示它。
9.3-显示HeroDetailComponent
这HeroesComponent仍然是主/细节视图。
它用于在切割模板的该部分之前自行显示英雄详细信息。现在它将委托给HeroDetailComponent。
这两个组件将具有父母/子女关系。父母HeroesComponent将HeroDetailComponent 通过发送一个新的英雄来控制孩子,以便在用户从列表中选择英雄时显示。
你不会改变HeroesComponent 班级,但你会改变它的模板。
更新HeroesComponent模板
该HeroDetailComponent选择是‘app-hero-detail‘。<app-hero-detail>在HeroesComponent模板底部附近添加一个元素,其中英雄细节视图曾经是。
像这样绑定HeroesComponent.selectedHero元素的hero属性。
heroes.component.html(HeroDetail绑定)
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
[hero]="selectedHero"是一个Angular 属性绑定。
这是一个单向的数据从绑定selectedHero的属性HeroesComponent的hero目标元素,它映射到的财产hero的性质HeroDetailComponent。
现在,当用户点击列表中的英雄时,selectedHero就会发生变化。当selectedHero更改时,属性绑定更新hero 并HeroDetailComponent显示新的英雄。
修改后的HeroesComponent模板应该如下所示:
<h2>My Heroes</h2> <ul class="heroes"> <li *ngFor="let hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> </ul> <app-hero-detail [hero]="selectedHero"></app-hero-detail>
浏览器刷新并且应用程序重新开始工作,就像以前一样。
什么改变?
和以前一样,只要用户点击英雄名字,英雄详情就会出现在英雄列表下方。现在HeroDetailComponent是呈现这些细节,而不是HeroesComponent。
将原件重构HeroesComponent为两个组件,现在和未来都会带来好处:
-
你
HeroesComponent通过减少责任来简化它。 -
你可以演变
HeroDetailComponent成一个丰富的英雄编辑器,而无需触摸父母HeroesComponent。 -
你可以在
HeroesComponent不触及英雄细节视图的情况下进化。 -
您可以重新使用
HeroDetailComponent未来组件的模板。
src/app/herodetail.component.html
<div *ngIf="hero"> <h2>{{ hero.name | uppercase }} Details</h2> <div><span>id: </span>{{hero.id}}</div> <div> <label>name: <input [(ngModel)]="hero.name" placeholder="name"/> </label> </div> </div>
src/app/herodetail.component.ts
import { Component, OnInit, Input } from ‘@angular/core‘; import { Hero } from ‘../hero‘; @Component({ selector: ‘app-hero-detail‘, templateUrl: ‘./hero-detail.component.html‘, styleUrls: [‘./hero-detail.component.css‘] }) export class HeroDetailComponent implements OnInit { @Input() hero: Hero; constructor() { } ngOnInit() { } }
src/app/heroes/heroes.component.ts
<h2>My Heroes</h2> <ul class="heroes"> <li *ngFor="let hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> </ul> <app-hero-detail [hero]="selectedHero"></app-hero-detail>