此刻,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>