您好,登錄后才能下訂單哦!
在本頁面,你將擴展《英雄指南》應用,讓它顯示一個英雄列表, 并允許用戶選擇一個英雄,查看該英雄的詳細信息。
你需要一些英雄數據以供顯示。
最終,你會從遠端的數據服務器獲取它。但是目前,你需要創建一些模擬英雄(some?mock heroes),并假設這些數據是從遠程服務器上獲取的。
在?src/app/
?文件夾中創建一個名叫?mock-heroes.ts
?的文件。 定義一個包含十個英雄的常量數組?HEROES
,并導出它。 該文件是這樣的。
src/app/mock-heroes.ts
import ?{ Hero } from? './hero' ; ? export? const ?HEROES: Hero[] = [ ?? { id:? 11 , name:? 'Mr. Nice' ?}, ?? { id:? 12 , name:? 'Narco' ?}, ?? { 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
?的頂部顯示這個英雄列表。
打開?HeroesComponent
?類文件,并導入模擬的?HEROES 數據。
src/app/heroes/heroes.component.ts
import ?{ HEROES } from? '../mock-heroes' ; |
往類中添加一個?heroes
?屬性,這樣可以暴露出這些英雄,以供綁定。
src/app/heroes/heroes.component.ts
export? class ?HeroesComponent? implements ?OnInit { ? ?? heroes = HEROES; |
*
ngFor?列出這些英雄打開?HeroesComponent
?的模板文件,并做如下修改:
在頂部添加?<h3>
然后添加表示無序列表的 HTML 元素(<ul>
)
在?<ul>
?中插入一個?<li>
?元素,以顯示單個?hero
?的屬性。
點綴上一些 CSS 類(稍后你還會添加更多 CSS 樣式)。
完成后應該如下顯示:
heroes.component.html
heroes.component.html (heroes template) content_copy <h3>My Heroes</h3> <ul? class = "heroes" > ?? <li> ???? <span? class = "badge" >{{hero.id}}</span> {{hero.name}} ?? </li> </ul> |
現在,把?<li>
?修改成這樣:
<li *ngFor= "let hero of heroes" > |
*ngFor
?是一個 Angular 的復寫器(repeater)指令。 它會為列表中的每項數據復寫它的宿主元素。
在這個例子中
<li>
?就是?*
ngFor?的宿主元素
heroes
?就是來自?HeroesComponent
?類的列表。
當依次遍歷這個列表時,hero
?會為每個迭代保存當前的英雄對象。
不要忘了?ngFor?前面的星號(*
),它是該語法中的關鍵部分。
瀏覽器刷新之后,英雄列表出現了。
英雄列表應該富有吸引力,并且當用戶把鼠標移到某個英雄上和從列表中選中某個英雄時,應該給出視覺反饋。
在教程的第一章,你曾在?styles.css
?中為整個應用設置了一些基礎的樣式。 但那個樣式表并不包含英雄列表所需的樣式。
固然,你可以把更多樣式加入到?styles.css
,并且放任它隨著你添加更多組件而不斷膨脹。
但還有更好的方式。你可以定義屬于特定組件的私有樣式,并且讓組件所需的一切(代碼、HTML 和 CSS)都放在一起。
這種方式讓你在其它地方復用該組件更加容易,并且即使全局樣式和這里不一樣,組件也仍然具有期望的外觀。
你可以用多種方式定義私有樣式,或者內聯在?@
Component.styles?數組中,或者在?@
Component.styleUrls?所指出的樣式表文件中。
當 CLI 生成?HeroesComponent
?時,它也同時為?HeroesComponent
?創建了空白的?heroes.component.css
?樣式表文件,并且讓?@
Component.styleUrls?指向它,就像這樣:
src/app/heroes/heroes.component.ts
@Component ({ ?? selector:? 'app-heroes' , ?? templateUrl:? './heroes.component.html' , ?? styleUrls: [ './heroes.component.css' ] }) |
打開?heroes.component.css
?文件,并且把?HeroesComponent
?的私有 CSS 樣式粘貼進去。 你可以在本指南底部的查看最終代碼中找到它們。
@
Component?元數據中指定的樣式和樣式表都是局限于該組件的。?heroes.component.css
?中的樣式只會作用于?HeroesComponent
,既不會影響到組件外的 HTML,也不會影響到其它組件中的 HTML。
當用戶在主列表中點擊一個英雄時,該組件應該在頁面底部顯示所選英雄的詳情。
在本節,你將監聽英雄條目的點擊事件,并更新英雄的詳情。
click
?事件綁定再往?<li>
?元素上插入一句點擊事件的綁定代碼:
heroes.component.html
<li *ngFor= "let hero of heroes" ?(click)= "onSelect(hero)" > |
這是 Angular?事件綁定?語法的例子。
click
?外面的圓括號會讓 Angular 監聽這個?<li>
?元素的?click
?事件。 當用戶點擊?<li>
?時,Angular 就會執行表達式?onSelect(hero)
。
onSelect()
?是?HeroesComponent
?上的一個方法,你很快就要寫它。 Angular 會把所點擊的?<li>
?上的?hero
?對象傳給它,這個?hero
?也就是前面在?*
ngFor?表達式中定義的那個。
click
?事件處理器把該組件的?hero
?屬性改名為?selectedHero
,但不要為它賦值。 因為應用剛剛啟動時并沒有所選英雄。
添加如下?onSelect()
?方法,它會把模板中被點擊的英雄賦值給組件的?selectedHero
?屬性。
src/app/heroes/heroes.component.ts
selectedHero: Hero; onSelect(hero: Hero):? void ?{ ?? this .selectedHero = hero; } |
該模板引用的仍然是老的?hero
?屬性,但它已經不存在了。 把?hero
?改名為?selectedHero
。
heroes.component.html
<h3>{{selectedHero.name | uppercase}} Details</h3> <div><span>id: </span>{{selectedHero.id}}</div> <div> ?? <label>name: ???? <input [(ngModel)]= "selectedHero.name" ?placeholder= "name" > ?? </label> </div> |
刷新瀏覽器,應用掛了。
打開瀏覽器的開發者工具,它的控制臺中顯示出如下錯誤信息:
HeroesComponent.html: 3 ?ERROR TypeError: Cannot read property? 'name' ?of undefined |
當應用啟動時,selectedHero
?是?undefined
,設計如此。
但模板中的綁定表達式引用了?selectedHero
?的屬性(表達式為?{{
selectedHero.name}}
),這必然會失敗,因為你還沒選過英雄呢。
現在,從列表中隨便點擊一個條目。 應用又正常了。 英雄們顯示在列表中,并且所點英雄的詳情也顯示在了頁面的下方。
該組件應該只有當?selectedHero
?存在時才顯示所選英雄的詳情。
把顯示英雄詳情的 HTML 包裹在一個?<div>
?中。 并且為這個 div 添加 Angular 的?*
ngIf?指令,把它的值設置為?selectedHero
。
不要忘了?ngIf?前面的星號(*
),它是該語法中的關鍵部分。
src/app/heroes/heroes.component.html (*ngIf)
<div *ngIf= "selectedHero" > ? ?? <h3>{{selectedHero.name | uppercase}} Details</h3> ?? <div><span>id: </span>{{selectedHero.id}}</div> ?? <div> ???? <label>name: ?????? <input [(ngModel)]= "selectedHero.name" ?placeholder= "name" > ???? </label> ?? </div> ? </div> |
瀏覽器刷新之后,英雄名字的列表又出現了。 詳情部分仍然是空。 點擊一個英雄,它的詳情就出現了。 這個應用看起來又再次工作正常顯示了。 英雄顯示在列表中,當你單擊英雄的名字的時候,有關你單擊英雄的詳細信息就顯示在頁面的底部了。
當?selectedHero
?為?undefined
?時,ngIf?從 DOM 中移除了英雄詳情。因此也就不用擔心?selectedHero
?的綁定了。
當用戶選擇一個英雄時,selectedHero
?也就有了值,并且?ngIf?把英雄的詳情放回到 DOM 中。
所有的?<li>
?元素看起來都是一樣的,因此很難從列表中識別出所選英雄。
如果用戶點擊了“Magneta”,這個英雄應該用一個略有不同的背景色顯示出來,就像這樣:
所選英雄的顏色來自于你前面添加的樣式中的 CSS 類?.selected
。 所以你只要在用戶點擊一個?<li>
?時把?.selected
?類應用到該元素上就可以了。
Angular 的?CSS 類綁定機制讓根據條件添加或移除一個 CSS 類變得很容易。 只要把?[class.some-css-class]="some-condition"
?添加到你要施加樣式的元素上就可以了。
在?HeroesComponent
?模板中的?<li>
?元素上添加?[class.selected]
?綁定,代碼如下:
heroes.component.html (toggle the 'selected' CSS class)
[ class .selected]= "hero === selectedHero" |
如果當前行的英雄和?selectedHero
?相同,Angular 就會添加 CSS 類?selected
,否則就會移除它。
最終的?<li>
?是這樣的:
heroes.component.html (list item hero)
<li *ngFor= "let hero of heroes" ?? [ class .selected]= "hero === selectedHero" ?? (click)= "onSelect(hero)" > ?? <span? class = "badge" >{{hero.id}}</span> {{hero.name}} </li> |
你的應用現在變成了這樣:在線例子?/?下載范例。
下面是本頁面中所提及的代碼文件,包括?HeroesComponent
?的樣式。
對應的文件列表和代碼鏈接如下:
文件名 | 源代碼 |
---|---|
src/app/heroes/heroes.component.ts | https://github.com/cwiki-us-angular/cwiki-us-angular-tour-of-heroes-list/blob/master/src/app/heroes/heroes.component.ts |
src/app/heroes/heroes.component.html | https://github.com/cwiki-us-angular/cwiki-us-angular-tour-of-heroes-list/blob/master/src/app/heroes/heroes.component.html |
src/app/heroes/heroes.component.css | https://github.com/cwiki-us-angular/cwiki-us-angular-tour-of-heroes-list/blob/master/src/app/heroes/heroes.component.css |
英雄指南應用在一個主從視圖中顯示了英雄列表。
用戶可以選擇一個英雄,并查看該英雄的詳情。
你使用?*
ngFor?顯示了一個列表。
你使用?*
ngIf?來根據條件包含或排除了一段 HTML。
你可以用?class
?綁定來切換 CSS 的樣式類。
https://www.cwiki.us/display/AngularZH/Display+a+Heroes+List
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。