應(yīng)用程序現(xiàn)在有了基本的標(biāo)題。 接下來您要?jiǎng)?chuàng)建一個(gè)新的組件來顯示英雄信息并且把這個(gè)組件放到應(yīng)用程序的外殼里去。
使用 Angular CLI 創(chuàng)建一個(gè)名為 heroes 的新組件
ng generate component heroes
CLI 創(chuàng)建了一個(gè)新的文件夾 "src/app/heroes/",并生成了 HeroesComponent 的四個(gè)文件。其類文件如下:
Path:"app/heroes/heroes.component.ts (initial version)"
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
你要從 Angular 核心庫(kù)中導(dǎo)入 Component 符號(hào),并為組件類加上 @Component 裝飾器。
@Component 是個(gè)裝飾器函數(shù),用于為該組件指定 Angular 所需的元數(shù)據(jù)。
CLI 自動(dòng)生成了三個(gè)元數(shù)據(jù)屬性:
CSS 元素選擇器 app-heroes
用來在父組件的模板中匹配 HTML 元素的名稱,以識(shí)別出該組件。
ngOnInit()
是一個(gè)生命周期鉤子,Angular 在創(chuàng)建完組件后很快就會(huì)調(diào)用 ngOnInit()
。這里是放置初始化邏輯的好地方。
始終要 export 這個(gè)組件類,以便在其它地方(比如 AppModule)導(dǎo)入它。
往 HeroesComponent 中添加一個(gè) hero 屬性,用來表示一個(gè)名叫 “W3Cschool” 的英雄。
Path:"heroes.component.ts (hero property)"
hero = 'Windstorm';
打開模板文件 "heroes.component.html"。刪除 Angular CLI 自動(dòng)生成的默認(rèn)內(nèi)容,改為到 hero 屬性的數(shù)據(jù)綁定。
Path:"heroes.component.html"
{{hero}}
要顯示 HeroesComponent 你必須把它加到殼組件 AppComponent 的模板中。
別忘了,app-heroes
就是 HeroesComponent 的 元素選擇器。 所以,只要把 <app-heroes>
元素添加到 AppComponent 的模板文件中就可以了,就放在標(biāo)題下方。
Path:"src/app/app.component.html"
<h1>{{title}}</h1>
<app-heroes></app-heroes>
如果 CLI 的 ng serve
命令仍在運(yùn)行,瀏覽器就會(huì)自動(dòng)刷新,并且同時(shí)顯示出應(yīng)用的標(biāo)題和英雄的名字。
真實(shí)的英雄當(dāng)然不止一個(gè)名字。
在 src/app
文件夾中為 Hero 類創(chuàng)建一個(gè)文件,并添加 id 和 name 屬性。
Path:"src/app/hero.ts"
export interface Hero {
id: number;
name: string;
}
回到 HeroesComponent 類,并且導(dǎo)入這個(gè) Hero 類。
把組件的 hero 屬性的類型重構(gòu)為 Hero。 然后以 1 為 id、以 “W3Cschool” 為名字初始化它。
修改后的 HeroesComponent 類如下:
Path:"src/app/heroes/heroes.component.ts"
import { Component, OnInit } from '@angular/core';
import { Hero } from '../hero';
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
hero: Hero = {
id: 1,
name: 'Windstorm'
};
constructor() { }
ngOnInit() {
}
}
頁(yè)面顯示變得不正常了,因?yàn)槟銊倓偘?hero 從字符串改成了對(duì)象。
修改模板中的綁定,以顯示英雄的名字,并在詳情中顯示 id 和 name,就像這樣:
Path:"heroes.component.html (HeroesComponent's template)"
<h2>{{hero.name}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div><span>name: </span>{{hero.name}}</div>
瀏覽器自動(dòng)刷新,并顯示這位英雄的信息。
把 hero.name 的綁定修改成這樣:
Path:"src/app/heroes/heroes.component.html"
<h2>{{hero.name | uppercase}} Details</h2>
瀏覽器刷新了。現(xiàn)在,英雄的名字顯示成了大寫字母。
綁定表達(dá)式中的 uppercase 位于管道操作符( |
)的右邊,用來調(diào)用內(nèi)置管道 UppercasePipe。
管道 是格式化字符串、金額、日期和其它顯示數(shù)據(jù)的好辦法。 Angular 發(fā)布了一些內(nèi)置管道,而且你還可以創(chuàng)建自己的管道。
用戶應(yīng)該能在一個(gè) <input>
輸入框中編輯英雄的名字。
當(dāng)用戶輸入時(shí),這個(gè)輸入框應(yīng)該能同時(shí)顯示和修改英雄的 name
屬性。 也就是說,數(shù)據(jù)流從組件類流出到屏幕,并且從屏幕流回到組件類。
要想讓這種數(shù)據(jù)流動(dòng)自動(dòng)化,就要在表單元素 <input>
和組件的 hero.name
屬性之間建立雙向數(shù)據(jù)綁定。
把模板中的英雄詳情區(qū)重構(gòu)成這樣:
Path:"src/app/heroes/heroes.component.html (HeroesComponent's template)"
<div>
<label>name:
<input [(ngModel)]="hero.name" placeholder="name"/>
</label>
</div>
[(ngModel)]
是 Angular 的雙向數(shù)據(jù)綁定語(yǔ)法。
這里把 hero.name
屬性綁定到了 HTML 的 textbox 元素上,以便數(shù)據(jù)流可以雙向流動(dòng):從 hero.name
屬性流動(dòng)到 textbox,并且從 textbox 流回到 hero.name
。
注意,當(dāng)你加上 [(ngModel)]
之后這個(gè)應(yīng)用無(wú)法工作了。
打開瀏覽器的開發(fā)工具,就會(huì)在控制臺(tái)中看到如下信息:
Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'input'.
雖然 ngModel
是一個(gè)有效的 Angular 指令,不過它在默認(rèn)情況下是不可用的。
它屬于一個(gè)可選模塊 FormsModule,你必須自行添加此模塊才能使用該指令。
Angular 需要知道如何把應(yīng)用程序的各個(gè)部分組合到一起,以及該應(yīng)用需要哪些其它文件和庫(kù)。 這些信息被稱為元數(shù)據(jù)(metadata)。
有些元數(shù)據(jù)位于 @Component
裝飾器中,你會(huì)把它加到組件類上。 另一些關(guān)鍵性的元數(shù)據(jù)位于 @NgModule
裝飾器中。
最重要的 @NgModule 裝飾器位于頂層類 AppModule 上。
Angular CLI 在創(chuàng)建項(xiàng)目的時(shí)候就在 "src/app/app.module.ts" 中生成了一個(gè) AppModule 類。 這里也就是你要添加 FormsModule 的地方。
打開 AppModule (app.module.ts) 并從 @angular/forms 庫(kù)中導(dǎo)入 FormsModule 符號(hào)。
Path:"app.module.ts (FormsModule symbol import)"
import { FormsModule } from '@angular/forms'; // <-- NgModel lives here
然后把 FormsModule 添加到 @NgModule 元數(shù)據(jù)的 imports 數(shù)組中,這里是該應(yīng)用所需外部模塊的列表。
Path:"app.module.ts (@NgModule imports)"
imports: [
BrowserModule,
FormsModule
],
刷新瀏覽器,應(yīng)用又能正常工作了。你可以編輯英雄的名字,并且會(huì)看到這個(gè)改動(dòng)立刻體現(xiàn)在這個(gè)輸入框上方的 <h2>
中。
每個(gè)組件都必須聲明在(且只能聲明在)一個(gè) NgModule 中。
你沒有聲明過 HeroesComponent,可為什么本應(yīng)用卻正常呢?
這是因?yàn)?Angular CLI 在生成 HeroesComponent 組件的時(shí)候就自動(dòng)把它加到了 AppModule 中。
打開 "src/app/app.module.ts" 你就會(huì)發(fā)現(xiàn) HeroesComponent 已經(jīng)在頂部導(dǎo)入過了。
Path:"src/app/app.module.ts"
import { HeroesComponent } from './heroes/heroes.component';
HeroesComponent 也已經(jīng)聲明在了 @NgModule.declarations 數(shù)組中。
Path:"src/app/app.module.ts"
declarations: [
AppComponent,
HeroesComponent
],
注:
AppModule 聲明了應(yīng)用中的所有組件,AppComponent 和 HeroesComponent。
本篇設(shè)計(jì)的代碼如下:
import { Component, OnInit } from '@angular/core';
import { Hero } from '../hero';
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
hero: Hero = {
id: 1,
name: 'Windstorm'
};
constructor() { }
ngOnInit() {
}
}
<h2>{{hero.name | uppercase}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div>
<label>name:
<input [(ngModel)]="hero.name" placeholder="name"/>
</label>
</div>
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms'; // <-- NgModel lives here
import { AppComponent } from './app.component';
import { HeroesComponent } from './heroes/heroes.component';
@NgModule({
declarations: [
AppComponent,
HeroesComponent
],
imports: [
BrowserModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Tour of Heroes';
}
<h1>{{title}}</h1>
<app-heroes></app-heroes>
export interface Hero {
id: number;
name: string;
}
UppercasePipe
來格式化英雄的名字。ngModel
指令實(shí)現(xiàn)了雙向數(shù)據(jù)綁定。FormsModule
導(dǎo)入了 AppModule
,以便 Angular 能識(shí)別并應(yīng)用 ngModel
指令。AppModule
是很重要的,并認(rèn)識(shí)到 CLI 會(huì)自動(dòng)幫你聲明它。
更多建議: