# Day08 【牙起來】 物件、陣列、ngFor、ngIf - 程式面介紹 再來換到**商店store**區塊 商店嘛,總是要販售一些**武器**和**防具**的 不然裸裝的冒險者早晚都死光了 ## 程式內的物件 Object 於是在 `store.component.ts` 中加入 **weapon**物件 我要一把**小劍**,他的**攻擊力**是5 `{name: '小劍', atk: '5'}` ```typescript= ... export class StoreComponent implements OnInit { weapon = {name: '小劍', atk: '5'}; constructor() { } ngOnInit(): void { } } ``` 接下來你知道的,還要修改樣板 `store.component.html` ```html= <h2>商店區塊</h2> <div>武器: {{weapon}}</div> ``` 來看一下吧 ![](https://i.imgur.com/umYP2FB.png) 诶?奇怪 我的小劍跟攻擊力5去哪了? 為什麼是出現`[object Object]`呢? 我們分別使用 `alert` 與 `console.log` 印出來看看 ```typescript= ... export class StoreComponent implements OnInit { weapon = {name: '小劍', atk: '5'}; constructor() { } ngOnInit(): void { alert(this.weapon); console.log(this.weapon); } } ``` 使用 `alert` 也一樣,印物件只會出現`Object`、而非物物件內部結構 ![](https://i.imgur.com/pxhTrja.png) > 這邊能用 `JSON.stringify()` 把物件以字串方式印出來看 使用 `console.log` 則可以看到物件內部結構 ![](https://i.imgur.com/LxApLpk.png) ### 管線 pipe 要在Angular樣板上印出完整物件,可以使用**json pipe** 透過將物件轉換成json格式再印出來 修改 `store.component.html` ```html= <h2>商店區塊</h2> <div>武器: {{weapon | json}}</div> ``` 在綁定的變數後方加上` | json` ,其中這一槓 `|` 代表的就是**管線 pipe** > 關於pipe元件會在之後的章節再次提及 印出物件的畫面 ![](https://i.imgur.com/Xa2psfw.png) ### 取得物件底下的成員 分別印出武器物件底下的 **名稱 name** 跟 **攻擊力 atk** 透過以下兩種方式都可以取得物件底下的數值 * 物件的點點`.`來取得成員 * `['']` 來索引物件 ```html= <h2>商店區塊</h2> <div>武器名稱: {{weapon.name}}</div> <div>武器攻擊力: {{weapon['atk']}}</div> ``` ![](https://i.imgur.com/7uuxvqX.png) > 什麼,你說現在商店只有一把武器 不夠看、太過窮酸? > > 看來... 我們只好導入陣列了 ## 程式內的陣列 Array 武器變成多把,所以把變數名稱改成 `weapons` 複數 然後以**陣列**包起這個物件 修改 `store.component.ts` ```typescript= export class StoreComponent implements OnInit { weapons = [ {name: '小劍', atk: '5'}, {name: '彎刀', atk: '7'}, {name: '大魔劍', atk: '11'}, ]; constructor() { } ngOnInit(): void { } } ``` 因為 `weapons` 變成陣列型態了,所以樣板也需要加入 `[0]` 來索引陣列 ```html= <h2>商店區塊</h2> <div>武器名稱: {{weapons[0].name}}</div> <div>武器攻擊力: {{weapons[0]['atk']}}</div> ``` --- ## 樣板中的For迴圈 - `*ngFor` 有三樣武器,如果要透過HTML印出來 一樣一樣指定 `weapons[0]`、`weapons[1]`、`weapons[2]` 也太麻煩了 所以Angular在樣板中也有 **For 迴圈** ,叫作 **`*ngFor`** 修改 `store.component.html` ```html= <h2>商店區塊</h2> <div *ngFor="let weapon of weapons"> <div>武器名稱: {{weapon.name}}</div> <div>武器攻擊力: {{weapon['atk']}}</div> <br> </div> ``` 因為迴圈需要一層空間來**指定loop的範疇**,所以`ngFor`會放在要循環結構的外面 用法為`*ngFor = let ... of ...` ![](https://i.imgur.com/m3vFTfE.png) 修改後結果 ![](https://i.imgur.com/b6hwBdY.png) ### 迴圈的索引值 index 若想將武器商品編號,需要For迴圈中的**索引值**時 可在 `ngFor` 的地方加上`let ... = index` 便可以引用索引編號,索引值index從`0`開始 修改 `store.component.html` ```html= <h2>商店區塊</h2> <div *ngFor="let weapon of weapons; let i = index"> <div>武器編號: {{i + 1}}</div> <div>武器名稱: {{weapon.name}}</div> <div>武器攻擊力: {{weapon['atk']}}</div> <br> </div> ``` > 什麼,你覺得這波操作挺稀鬆平常? > > 拜託,這裡可是HTML樣板啊,原本可都是只寫標籤元素的地方 > 能在這裡寫code難道不驚訝嗎? > > 這都是Angular框架的功勞啊 --- 接下來替遊戲增加一點樂趣興 因為遊戲商店中,總會有一些玩樂性質的**垃圾武器**出現 譬如說接下來要登場的這一把 `只是名稱長了一點但沒有任何攻擊力` 的武器 修改 `store.component.ts` ```typescript= export class StoreComponent implements OnInit { weapons = [ {name: '小劍', atk: '5'}, {name: '彎刀', atk: '7'}, {name: '大魔劍', atk: '11'}, {name: '只是名稱長了一點但沒有任何攻擊力'}, ]; constructor() { } ngOnInit(): void { } } ``` 結果畫面 ![](https://i.imgur.com/8OpbNDy.png) ## 樣板中的if判斷 - `*ngIf` 因為 `只是名稱長了一點但沒有任何攻擊力` 這把武器真的沒有攻擊力的屬性 我想將他的 **武器攻擊力** 這一行隱藏掉,不然顯示在那也頗怪、挺佔位置的 這時候可以用**if 判斷式** `*ngIf` 修改 `store.component.html` ```html= <h2>商店區塊</h2> <div *ngFor="let weapon of weapons; let i = index"> <div>武器編號: {{i + 1}}</div> <div>武器名稱: {{weapon.name}}</div> <div *ngIf="weapon.atk">武器攻擊力: {{weapon['atk']}}</div> <br> </div> ``` 當 `weapon` 底下有 `atk` 這個屬性時,才會顯示**武器攻擊力**這一行 完成畫面 ![](https://i.imgur.com/GXLNhez.png) `*ngIf` 也可以有其他篩選條件 譬如**過濾武器**,只顯示**攻擊力為11**的武器 ```html= <h2>商店區塊</h2> <div *ngFor="let weapon of weapons; let i = index"> <div *ngIf="weapon.atk == '11'"> <div>武器編號: {{i + 1}}</div> <div>武器名稱: {{weapon.name}}</div> <div *ngIf="weapon.atk">武器攻擊力: {{weapon['atk']}}</div> <br> </div> </div> ``` 這邊的`'11'`因為是**字串**而非數字,所以用單引號`''`括起來 最終完成畫面 ![](https://i.imgur.com/pQHZSTY.png) --- > 恭喜到這一步已經完成 61% 的Angular > > 至於ngFor、ngIf為什麼要有那個星號`*`? > 因為星號表示[**循環結構的語法糖**](https://stackoverflow.com/questions/35498498/what-is-the-meaning-of-in-ngfor-in-angular2) > > 另外,[**ngIf跟ngFor沒辦法綁在同一個標籤上**](https://stackoverflow.com/questions/34657821/ngif-and-ngfor-on-same-element-causing-error)