W3Cschool
恭喜您成為首批注冊(cè)用戶(hù)
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
應(yīng)用程序現(xiàn)在有了基本的標(biāo)題。接下來(lái)你要?jiǎng)?chuàng)建一個(gè)新的組件來(lái)顯示英雄信息并且把這個(gè)組件放到應(yīng)用程序的外殼里去。
要查看本頁(yè)所講的范例程序,參閱現(xiàn)場(chǎng)演練 / 下載范例。
使用 Angular CLI 創(chuàng)建一個(gè)名為 ?heroes
?的新組件。
ng generate component heroes
CLI 創(chuàng)建了一個(gè)新的文件夾 ?src/app/heroes/
?,并生成了 ?HeroesComponent
?的四個(gè)文件。
?HeroesComponent
?的類(lèi)文件如下:
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(): void {
}
}
你要從 Angular 核心庫(kù)中導(dǎo)入 ?Component
?符號(hào),并為組件類(lèi)加上 ?@Component
? 裝飾器。
?@Component
? 是個(gè)裝飾器函數(shù),用于為該組件指定 Angular 所需的元數(shù)據(jù)。
CLI 自動(dòng)生成了三個(gè)元數(shù)據(jù)屬性:
屬性 |
詳情 |
---|---|
selector
|
組件的 CSS 元素選擇器 |
templateUrl
|
組件模板文件的位置。 |
styleUrls
|
組件私有 CSS 樣式表文件的位置。 |
CSS 元素選擇器 ?app-heroes
? 用來(lái)在父組件的模板中匹配 HTML 元素的名稱(chēng),以識(shí)別出該組件。
?ngOnInit()
? 是一個(gè)生命周期鉤子,Angular 在創(chuàng)建完組件后很快就會(huì)調(diào)用 ?ngOnInit()
?。這里是放置初始化邏輯的好地方。
始終要 ?export
?這個(gè)組件類(lèi),以便在其它地方(比如 ?AppModule
?)導(dǎo)入它。
往 ?HeroesComponent
?中添加一個(gè) ?hero
?屬性,用來(lái)表示一個(gè)名叫 “Windstorm” 的英雄。
hero = 'Windstorm';
打開(kāi)模板文件 ?heroes.component.html
?。刪除 Angular CLI 自動(dòng)生成的默認(rèn)內(nèi)容,改為到 ?hero
?屬性的數(shù)據(jù)綁定。
<h2>{{hero}}</h2>
要顯示 ?HeroesComponent
?你必須把它加到殼組件 ?AppComponent
?的模板中。
別忘了,?app-heroes
? 就是 ?HeroesComponent
?的 元素選擇器。 所以,只要把 ?<app-heroes>
? 元素添加到 ?AppComponent
?的模板文件中就可以了,就放在標(biāo)題下方。
<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
?類(lèi)創(chuàng)建一個(gè)文件,并添加 ?id
?和 ?name
?屬性。
export interface Hero {
id: number;
name: string;
}
回到 ?HeroesComponent
?類(lèi),并且導(dǎo)入這個(gè) ?Hero
?類(lèi)。
把組件的 ?hero
?屬性的類(lèi)型重構(gòu)為 ?Hero
?。然后以 ?1
? 為 ?id
?、以 “Windstorm” 為名字初始化它。
修改后的 ?HeroesComponent
?類(lèi)應(yīng)該是這樣的:
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(): void {
}
}
頁(yè)面顯示變得不正常了,因?yàn)槟銊倓偘?nbsp;?hero
?從字符串改成了對(duì)象。
修改模板中的綁定,以顯示英雄的名字,并在詳情中顯示 ?id
?和 ?name
?,就像這樣:
<h2>{{hero.name}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div><span>name: </span>{{hero.name}}</div>
瀏覽器自動(dòng)刷新,并顯示這位英雄的信息。
把 ?hero.name
? 的綁定修改成這樣。
<h2>{{hero.name | uppercase}} Details</h2>
瀏覽器刷新了?,F(xiàn)在,英雄的名字顯示成了大寫(xiě)字母。
綁定表達(dá)式中的 ?uppercase
?位于管道操作符(?|
?)的右邊,用來(lái)調(diào)用內(nèi)置管道 ?UppercasePipe
?。
管道 是格式化字符串、金額、日期和其它顯示數(shù)據(jù)的好辦法。Angular 發(fā)布了一些內(nèi)置管道,而且你還可以創(chuàng)建自己的管道。
用戶(hù)應(yīng)該能在一個(gè) ?<input>
? 輸入框中編輯英雄的名字。
當(dāng)用戶(hù)輸入時(shí),這個(gè)輸入框應(yīng)該能同時(shí)顯示和修改英雄的 ?name
?屬性。也就是說(shuō),數(shù)據(jù)流從組件類(lèi)流出到屏幕,并且從屏幕流回到組件類(lèi)。
要想讓這種數(shù)據(jù)流動(dòng)自動(dòng)化,就要在表單元素 ?<input>
? 和組件的 ?hero.name
? 屬性之間建立雙向數(shù)據(jù)綁定。
把模板中的英雄詳情區(qū)重構(gòu)成這樣:
<div>
<label for="name">Hero name: </label>
<input id="name" [(ngModel)]="hero.name" placeholder="name">
</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ú)法工作了。
打開(kāi)瀏覽器的開(kāi)發(fā)工具,就會(huì)在控制臺(tái)中看到如下信息:
Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'input'.
雖然 ?ngModel
?是一個(gè)有效的 Angular 指令,不過(guò)它在默認(rèn)情況下是不可用的。
它屬于一個(gè)可選模塊 ?FormsModule
?,你必須自行添加此模塊才能使用該指令。
Angular 需要知道如何把應(yīng)用程序的各個(gè)部分組合到一起,以及該應(yīng)用需要哪些其它文件和庫(kù)。這些信息被稱(chēng)為元數(shù)據(jù)(metadata)。
有些元數(shù)據(jù)位于 ?@Component
? 裝飾器中,你會(huì)把它加到組件類(lèi)上。另一些關(guān)鍵性的元數(shù)據(jù)位于 ?@NgModule
? 裝飾器中。
最重要的 ?@NgModule
? 裝飾器位于頂層類(lèi) AppModule 上。
Angular CLI 在創(chuàng)建項(xiàng)目的時(shí)候就在 ?src/app/app.module.ts
? 中生成了一個(gè) ?AppModule
?類(lèi)。這里也就是你要添加 ?FormsModule
?的地方。
打開(kāi) ?AppModule
?(?app.module.ts
?) 并從 ?@angular/forms
? 庫(kù)中導(dǎo)入 ?FormsModule
?符號(hào)。
import { FormsModule } from '@angular/forms'; // <-- NgModel lives here
然后把 ?FormsModule
?添加到 ?@NgModule
? 元數(shù)據(jù)的 ?imports
?數(shù)組中,這里是該應(yīng)用所需外部模塊的列表。
imports: [
BrowserModule,
FormsModule
],
刷新瀏覽器,應(yīng)用又能正常工作了。你可以編輯英雄的名字,并且會(huì)看到這個(gè)改動(dòng)立刻體現(xiàn)在這個(gè)輸入框上方的 ?<h2>
? 中。
每個(gè)組件都必須聲明在(且只能聲明在)一個(gè) ?NgModule
?中。
你沒(méi)有聲明過(guò) ?HeroesComponent
?,可為什么本應(yīng)用卻正常呢?
這是因?yàn)?nbsp;Angular CLI 在生成 ?HeroesComponent
?組件的時(shí)候就自動(dòng)把它加到了 ?AppModule
?中。
打開(kāi) ?src/app/app.module.ts
? 你就會(huì)發(fā)現(xiàn) ?HeroesComponent
?已經(jīng)在頂部導(dǎo)入過(guò)了。
import { HeroesComponent } from './heroes/heroes.component';
?HeroesComponent
?也已經(jīng)聲明在了 ?@NgModule.declarations
? 數(shù)組中。
declarations: [
AppComponent,
HeroesComponent
],
注意:
?AppModule
?聲明了應(yīng)用中的所有組件,?AppComponent
?和 ?HeroesComponent
?。
下面是本頁(yè)所提到的源代碼。
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(): void {
}
}
<h2>{{hero.name | uppercase}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div>
<label for="name">Hero name: </label>
<input id="name" [(ngModel)]="hero.name" placeholder="name">
</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;
}
HeroesComponent
?HeroesComponent
?添加到了殼組件 ?AppComponent
?中,以便顯示它
UppercasePipe
?來(lái)格式化英雄的名字
ngModel
?指令實(shí)現(xiàn)了雙向數(shù)據(jù)綁定
AppModule
?FormsModule
?導(dǎo)入了 ?AppModule
?,以便 Angular 能識(shí)別并應(yīng)用 ?ngModel
?指令
AppModule
?是很重要的,并認(rèn)識(shí)到 CLI 會(huì)自動(dòng)幫你聲明它Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話(huà):173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: