W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
本頁中,你將擴(kuò)展《英雄之旅》應(yīng)用,讓它顯示一個(gè)英雄列表,并允許用戶選擇一個(gè)英雄,查看該英雄的詳細(xì)信息。
要查看本頁所講的范例程序,參閱現(xiàn)場(chǎng)演練 / 下載范例。
你需要一些英雄數(shù)據(jù)以供顯示。
最終,你會(huì)從遠(yuǎn)端的數(shù)據(jù)服務(wù)器獲取它。不過目前,你要先創(chuàng)建一些模擬的英雄數(shù)據(jù),并假裝它們是從服務(wù)器上取到的。
在 ?src/app/
? 文件夾中創(chuàng)建一個(gè)名叫 ?mock-heroes.ts
? 的文件。定義一個(gè)包含十個(gè)英雄的常量數(shù)組 ?HEROES
?,并導(dǎo)出它。該文件是這樣的。
import { Hero } from './hero';
export const HEROES: Hero[] = [
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr. IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
打開 ?HeroesComponent
?類文件,并導(dǎo)入模擬的 ?HEROES
?。
import { HEROES } from '../mock-heroes';
往類中添加一個(gè) ?heroes
?屬性,這樣可以暴露出這個(gè) ?HEROES
?數(shù)組,以供綁定。
export class HeroesComponent implements OnInit {
heroes = HEROES;
}
打開 ?HeroesComponent
?的模板文件,并做如下修改:
<h2>
?。<ul>
? ) 元素。<ul>
? 中插入 ?<li>
?。<li>
? 中放一個(gè) ?<button>
? 元素,以便在 ?<span>
? 元素中顯示單個(gè) ?hero
?的屬性。做完之后應(yīng)該是這樣的:
<h2>My Heroes</h2>
<ul class="heroes">
<li>
<button type="button">
<span class="badge">{{hero.id}}</span>
<span class="name">{{hero.name}}</span>
</button>
</li>
</ul>
由于屬性 'hero' 不存在,因此會(huì)顯示一個(gè)錯(cuò)誤。要訪問每個(gè)英雄并列出所有英雄,請(qǐng)?jiān)?nbsp;?<li>
? 上添加 ?*ngFor
? 以遍歷英雄列表:
<li *ngFor="let hero of heroes">
?*ngFor
? 是一個(gè) Angular 的復(fù)寫器(repeater)指令。它會(huì)為列表中的每項(xiàng)數(shù)據(jù)復(fù)寫它的宿主元素。
這個(gè)例子中涉及的語法如下:
語法 |
詳情 |
---|---|
<li>
|
宿主元素。 |
heroes
|
來自 |
hero
|
保存列表每次迭代的當(dāng)前 hero 對(duì)象。 |
不要忘了 ?
ngFor
?前面的星號(hào)(?*
?),它是該語法中的關(guān)鍵部分。
瀏覽器刷新之后,英雄列表出現(xiàn)了。
交互元素
注意:
在 ?<li>
? 元素中,我們將英雄的詳細(xì)信息包裝在 ?<button>
? 元素中。稍后我們使 hero 可點(diǎn)擊,并且出于無障礙性的目的,最好使用本機(jī)交互式 HTML 元素(例如 ?<button>
?),而不是向非交互式元素添加事件偵聽器(例如 ?<li>
?)。
英雄列表應(yīng)該富有吸引力,并且當(dāng)用戶把鼠標(biāo)移到某個(gè)英雄上和從列表中選中某個(gè)英雄時(shí),應(yīng)該給出視覺反饋。
在教程的第一章,你曾在 ?styles.css
? 中為整個(gè)應(yīng)用設(shè)置了一些基礎(chǔ)的樣式。但那個(gè)樣式表并不包含英雄列表所需的樣式。
固然,你可以把更多樣式加入到 ?styles.css
?,并且放任它隨著你添加更多組件而不斷膨脹。
但還有更好的方式。你可以定義屬于特定組件的私有樣式,并且讓組件所需的一切(代碼、HTML 和 CSS)都放在一起。
這種方式讓你在其它地方復(fù)用該組件更加容易,并且即使全局樣式和這里不一樣,組件也仍然具有期望的外觀。
你可以用多種方式定義私有樣式,或者內(nèi)聯(lián)在 ?@Component.styles
? 數(shù)組中,或者在 ?@Component.styleUrls
? 所指出的樣式表文件中。
當(dāng) CLI 生成 ?HeroesComponent
?時(shí),它也同時(shí)為 ?HeroesComponent
?創(chuàng)建了空白的 ?heroes.component.css
? 樣式表文件,并且讓 ?@Component.styleUrls
? 指向它,就像這樣。
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
打開 ?heroes.component.css
? 文件,并且把 ?HeroesComponent
?的私有 CSS 樣式粘貼進(jìn)去。
?
@Component
? 元數(shù)據(jù)中指定的樣式和樣式表都是局限于該組件的。?heroes.component.css
? 中的樣式只會(huì)作用于 ?HeroesComponent
?,既不會(huì)影響到組件外的 HTML,也不會(huì)影響到其它組件中的 HTML。
當(dāng)用戶在此列表中點(diǎn)擊一個(gè)英雄時(shí),該組件應(yīng)該在頁面底部顯示所選英雄的詳情。
在本節(jié),你將監(jiān)聽英雄條目的點(diǎn)擊事件,并顯示與更新英雄的詳情。
為 ?<li>
? 中的 ?<button>
? 上添加一個(gè)點(diǎn)擊事件的綁定代碼:
<li *ngFor="let hero of heroes">
<button type="button" (click)="onSelect(hero)">
<!-- ... -->
?click
?外面的圓括號(hào)會(huì)讓 Angular 監(jiān)聽這個(gè) ?<button>
? 元素的 ?click
?事件。 當(dāng)用戶點(diǎn)擊 ?<button>
? 時(shí),Angular 就會(huì)執(zhí)行表達(dá)式 ?onSelect(hero)
?。
下一部分,會(huì)在 ?HeroesComponent
?上定義一個(gè) ?onSelect()
? 方法,用來顯示 ?*ngFor
? 表達(dá)式所定義的那個(gè)英雄(?hero
?)。
把該組件的 ?hero
?屬性改名為 ?selectedHero
?,但不要為它賦值。 因?yàn)閼?yīng)用剛剛啟動(dòng)時(shí)并沒有所選英雄。
添加如下 ?onSelect()
? 方法,它會(huì)把模板中被點(diǎn)擊的英雄賦值給組件的 ?selectedHero
?屬性。
selectedHero?: Hero;
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
現(xiàn)在,組件的模板中有一個(gè)列表。要想點(diǎn)擊列表中的一個(gè)英雄,并顯示該英雄的詳情,你需要在模板中留一個(gè)區(qū)域,用來顯示這些詳情。在 ?heroes.component.html
? 中該列表的緊下方,添加如下代碼:
<div *ngIf="selectedHero">
<h2>{{selectedHero.name | uppercase}} Details</h2>
<div>id: {{selectedHero.id}}</div>
<div>
<label for="hero-name">Hero name: </label>
<input id="hero-name" [(ngModel)]="selectedHero.name" placeholder="name">
</div>
</div>
只有在選擇英雄時(shí)才會(huì)顯示英雄詳細(xì)信息。最初創(chuàng)建組件時(shí),沒有所選的 hero,因此我們將 ?*ngIf
? 指令添加到包裝 hero 詳細(xì)信息的 ?<div>
? 中,以指示 Angular 僅在實(shí)際定義 ?selectedHero
?時(shí)(在它被通過點(diǎn)擊英雄來選擇)。
不要忘了 ?
ngIf
?前面的星號(hào)(?*
?),它是該語法中的關(guān)鍵部分。
為了標(biāo)出選定的英雄,你可以在以前添加過的樣式中增加 CSS 類 ?.selected
?。若要把 ?.selected
? 類應(yīng)用于此 <li> 上,請(qǐng)使用類綁定。
Angular 的類綁定可以有條件地添加和刪除 CSS 類。只需將 ?[class.some-css-class]="some-condition"
? 添加到要設(shè)置樣式的元素即可。
在 ?HeroesComponent
?模板中的 ?<button>
? 元素上添加 ?[class.selected]
? 綁定,代碼如下:
[class.selected]="hero === selectedHero"
如果當(dāng)前行的英雄和 ?selectedHero
?相同,Angular 就會(huì)添加 CSS 類 ?selected
?,否則就會(huì)移除它。
最終的 ?<li>
? 是這樣的:
<li *ngFor="let hero of heroes">
<button [class.selected]="hero === selectedHero" type="button" (click)="onSelect(hero)">
<span class="badge">{{hero.id}}</span>
<span class="name">{{hero.name}}</span>
</button>
</li>
下面是本頁面中所提及的代碼文件,包括 ?HeroesComponent
? 的樣式。
import { Hero } from './hero';
export const HEROES: Hero[] = [
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr. IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
import { Component, OnInit } from '@angular/core';
import { Hero } from '../hero';
import { HEROES } from '../mock-heroes';
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
heroes = HEROES;
selectedHero?: Hero;
constructor() { }
ngOnInit(): void {
}
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
}
<h2>My Heroes</h2>
<ul class="heroes">
<li *ngFor="let hero of heroes">
<button [class.selected]="hero === selectedHero" type="button" (click)="onSelect(hero)">
<span class="badge">{{hero.id}}</span>
<span class="name">{{hero.name}}</span>
</button>
</li>
</ul>
<div *ngIf="selectedHero">
<h2>{{selectedHero.name | uppercase}} Details</h2>
<div>id: {{selectedHero.id}}</div>
<div>
<label for="hero-name">Hero name: </label>
<input id="hero-name" [(ngModel)]="selectedHero.name" placeholder="name">
</div>
</div>
/* HeroesComponent's private CSS styles */
.heroes {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 15em;
}
.heroes li {
display: flex;
}
.heroes button {
flex: 1;
cursor: pointer;
position: relative;
left: 0;
background-color: #EEE;
margin: .5em;
padding: 0;
border-radius: 4px;
display: flex;
align-items: stretch;
height: 1.8em;
}
.heroes button:hover {
color: #2c3a41;
background-color: #e6e6e6;
left: .1em;
}
.heroes button:active {
background-color: #525252;
color: #fafafa;
}
.heroes button.selected {
background-color: black;
color: white;
}
.heroes button.selected:hover {
background-color: #505050;
color: white;
}
.heroes button.selected:active {
background-color: black;
color: white;
}
.heroes .badge {
display: inline-block;
font-size: small;
color: white;
padding: 0.8em 0.7em 0 0.7em;
background-color: #405061;
line-height: 1em;
margin-right: .8em;
border-radius: 4px 0 0 4px;
}
.heroes .name {
align-self: center;
}
*ngFor
? 顯示了一個(gè)列表。
*ngIf
? 來根據(jù)條件包含或排除了一段 HTML。
class
?綁定來切換 CSS 的樣式類。Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: