The AppComponent is doing everything at the moment.
In the beginning, it showed details of a single hero.
Then it became a master/detail form with both a list of heroes and the hero detail.
Soon there will be new requirements and capabilities.
You can't keep piling features on top of features in one component; that's not maintainable.
You'll need to break it up into sub-components, each focused on a specific task or workflow.
Eventually, the AppComponent could become a simple shell that hosts those sub-components.
In this page, you'll take the first step in that direction by carving out the hero details into a separate, reusable component.
When you're done, the app should look like this live example / downloadable example.
延续上一步教程
Where you left off
在继续《英雄指南》之前,先检查一下,是否已经有了如下目录结构。如果没有,回上一章,看看错过了哪里。
Before getting started on this page, verify that you have the following structure from earlier in the Tour of Heroes.
If not, go back to the previous pages.
The component class name should be written in upper camel case and end in the word "Component".
The hero detail component class is HeroDetailComponent.
The component file name should be spelled in lower dash case,
each word separated by dashes, and end in .component.ts.
The HeroDetailComponent class goes in the hero-detail.component.ts file.
The @Component decorator provides the Angular metadata for the component.
The CSS selector name, hero-detail, will match the element tag
that identifies this component within a parent component's template.
Near the end of this tutorial page,
you'll add a <hero-detail> element to the AppComponent template.
总是export这个组件类,因为你必然会在别处import它。
Always export the component class because you'll always import it elsewhere.
To move the hero detail view to the HeroDetailComponent,
cut the hero detail content from the bottom of the AppComponent template
and paste it into a new template property in the @Component metadata.
The HeroDetailComponent has a hero, not a selected hero.
Replace the word, "selectedHero", with the word, "hero", everywhere in the template.
When you're done, the new template should look like this:
The hero property is typed as an instance of Hero.
The Hero class is still in the app.component.ts file.
Now there are two components that need to reference the Hero class.
The Angular style guide recommends one class per file anyway.
因此我们要把Hero类从app.component.ts移到它自己的hero.ts文件中:
Move the Hero class from app.component.ts to its own hero.ts file.
Now that the Hero class is in its own file, the AppComponent and the HeroDetailComponent have to import it.
Add the following import statement near the top of both the app.component.ts and the hero-detail.component.ts files.
Later in this page,
the parent AppComponent will tell the child HeroDetailComponent which hero to display
by binding its selectedHero to the hero property of the HeroDetailComponent.
The binding will look like this:
Putting square brackets around the hero property, to the left of the equal sign (=),
makes it the target of a property binding expression.
You must declare a target binding property to be an input property.
Otherwise, Angular rejects the binding and throws an error.
首先,修改@angular/core导入语句,使其包含符号Input。
First, amend the @angular/core import statement to include the Input symbol.
src/app/hero-detail.component.ts (excerpt)
import{Component,Input}from'@angular/core';
然后,通过在hero属性前面加上@Input装饰器,来表明它是一个输入属性。
Then declare that hero is an input property by
preceding it with the @Input decorator that you imported earlier.
In general, the declarations array contains a list of application components, pipes, and directives that belong to the module.
A component must be declared in a module before other components can reference it.
This module declares only the two application components, AppComponent and HeroDetailComponent.
The AppComponent is still a master/detail view.
It used to display the hero details on its own, before you cut out that portion of the template.
Now it will delegate to the HeroDetailComponent.
Recall that hero-detail is the CSS selector
in the HeroDetailComponent metadata.
That's the tag name of the element that represents the HeroDetailComponent.
Coordinate the master AppComponent with the HeroDetailComponent
by binding the selectedHero property of the AppComponent
to the hero property of the HeroDetailComponent.
app.component.ts (excerpt)
<hero-detail [hero]="selectedHero"></hero-detail>
每当selectedHero变化时,HeroDetailComponent就会显示一个新的英雄。
Now every time the selectedHero changes, the HeroDetailComponent gets a new hero to display.
修改后的AppComponent模板是这样的:
The revised AppComponent template should look like this:
You learned to declare the required application directives in an Angular module. You
listed the directives in the NgModule decorator's declarations array.
我们学会了把父组件绑定到子组件。
You learned to bind a parent component to a child component.
The Tour of Heroes app is more reusable with shared components,
but its (mock) data is still hard coded within the AppComponent.
That's not sustainable.
Data access should be refactored to a separate service
and shared among the components that need data.