# Day09 【牙起來】 繫結3 屬性綁定 - 程式面介紹 以下三張圖分別代表 **小劍**、**彎刀**、**大魔劍** 三種武器 (圖片源自unsplash) 我們把這些圖示放入遊戲專案中 **小劍** ![小劍](https://i.imgur.com/R5lchoc.jpg) **彎刀** ![彎刀](https://i.imgur.com/rIjafZZ.jpg) **大魔劍** (圖片找得太尖細了... ![魔劍](https://i.imgur.com/A1DHORH.jpg) 在Angular專案架構中,會把這些照片等資源都放入`\src\assets` 底下 在這裡新建一個 `image` 資料夾 ![](https://i.imgur.com/PDdx6vG.png) > 這邊的 `.gitkeep` 可以用力刪除 > 因為git不會控管**空資料夾**,所以創一個檔案`.gitkeep`給git看 > 這資料夾底下有東西所以請控管他,用途僅此 然後把三張圖片放入到此資料夾中 ![](https://i.imgur.com/oW1aPrf.png) ## 原Html img引用圖片方法 透過原生的HTML引用圖片的方法 把 `<img src="...">` 放入For迴圈中,讓圖片循環的產生 同時為了避免超出邊界框,限制圖片高度 `height="150"` 修改 `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> <img src="assets/image/小劍.jpg" height="150" alt="武器"> <br><br> </div> ``` ![](https://i.imgur.com/HZknIrI.png) 但是這樣每張照片都一樣,照片每一把都是**小劍**,沒辦法達成預期 所以接下來要做的就是讓程式去控制要顯示的圖片 ## 屬性繫結 property binding 在程式內先寫好每把武器對應的圖片路徑 新建一個陣列 `imgSources`,依序存放圖片路徑 `['assets/image/小劍.jpg', 'assets/image/彎刀.jpg', 'assets/image/大魔劍.jpg']` 修改 `store.component.ts` ```typescript= ... export class StoreComponent implements OnInit { weapons = [ {name: '小劍', atk: '5'}, {name: '彎刀', atk: '7'}, {name: '大魔劍', atk: '11'} ]; imgSources = ['assets/image/小劍.jpg', 'assets/image/彎刀.jpg', 'assets/image/大魔劍.jpg'] constructor() { } ngOnInit(): void { } } ``` 接著使用 **屬性繫結** `[src]` 將程式陣列變數 與 圖片位置`src`做綁定 透過index來索引圖片陣列,顯示出第 `i` 個路徑的圖片位置 修改 `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> <img [src]="imgSources[i]" height="150" alt="武器"> <br><br> </div> ``` 被中括號`[]`包起來的attribute,就稱 **property** 這樣就大功告成啦~ 完成畫面 ![](https://i.imgur.com/BAgdKaB.png) ### 將圖片路徑寫在物件內 刪除 `imgSources` 陣列 改將圖片路徑寫在**Weapon物件**內,新增 `imgSrc` 屬性 這樣子的寫法也能達成相同效果 修改 `store.component.ts` ```typescript= export class StoreComponent implements OnInit { weapons = [ {name: '小劍', atk: '5', imgSrc: 'assets/image/小劍.jpg'}, {name: '彎刀', atk: '7', imgSrc: 'assets/image/彎刀.jpg'}, {name: '大魔劍', atk: '11', imgSrc: 'assets/image/大魔劍.jpg'} ]; constructor() { } ngOnInit(): void { } } ``` 接著修改 `store.component.html`,用 `weapon.imgSrc` 取得物件內的圖片路徑 ```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> <img [src]="weapon.imgSrc" height="150" alt="武器"> <br><br> </div> ``` ### 將圖片名稱以數字編號 若圖片檔名改以數字流水號來命名 ![](https://i.imgur.com/yDYYxer.png) 要取用時只需使用index `i` 的遞增特性 想辦法組合字串與變數,兜出檔案路徑名稱即可 將 `[src]` 修改為 `[src]="'assets/image/' + (i+1) +'.jpg'"` 修改 `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> <img [src]="'assets/image/' + (i+1) +'.jpg'" height="150" alt="武器"> <div>圖片路徑: {{'assets/image/' + (i+1) +'.jpg'}}</div> <br><br> </div> ``` 若對這一串還不是很了解的話 可以將兜出來的字串(圖片路徑),透過繫結綁定印出來看看 ![](https://i.imgur.com/Ys6ar5o.png) --- ### Attribute 與 Property 的差異 `Attribute` 與 `Property` 的中文都是**屬性**,這兩者有何差別?  HTML上的 `attribute` 會被轉為對應的DOM DOM上的各項數值的欄位稱為`property` * `attribute` 指的是 在HTML上就有的屬性 `<img src="assets/image/小劍.jpg" height="150" alt="武器">` 例如`src`、`height`、`alt` 這些都是 **attribute** * `property` 指的是 DOM上的元素 `<img [src]="'assets/image/小劍.jpg'" [height]="'150'" [alt]="'武器'">` 例如 `[src]`、`[height]`、`[alt]` 這些都是 **property** Angular讓我們能對著既有的**HTML Attribute** 在外層加上殼`[]` 變成**Property**,就可以對`值`進行操作 另外,Angular也可以在自定義的標籤上,帶入自定義的**Property**屬性值 這部分用法未來會再提及 ![](https://i.imgur.com/x1dlZKk.png) > 到這一步 恭喜你,已經學會69%的 Angular > > 以下部分不是非常重要,有興趣再看就好 --- ### 大部分情況下,修改 `property` 時會連動影響 `attribute` 譬如在HTML樣板中這樣子玩 (~~開發時這樣玩會被打死~~) 同時有 `src` 又有 `[src]`、同時有 `height` 又有 `[height]` 並且兩邊都設定成不同數值 ```html= <img src="assets/image/1.jpg" [src]="'assets/image/3.jpg'" height="9999999" [height]="'150'"> ``` ![](https://i.imgur.com/6mIwk7P.png) 結果可以看到 `attribute` 的值與 `property` 的值相同 等於`attribute`被屬性繫節的值覆蓋了 ### 不過也有例外 來看一個例子 在HTML上只留下 `<input>` 以及 預設值 `value` **勇者一號** ```html= <input type="text" value="勇者一號"> ``` 輸入框在被修改之前,`Attribute` 與 `Property` 都是 **勇者一號** ![](https://i.imgur.com/a2NwwT4.png) 接著手動輸入文字,將**勇者一號**改為**砲灰一號** 修改輸入框之後在開發工具中重新點擊一次該DOM ![](https://i.imgur.com/MmhKTah.png) 此時 `Property` 為**砲灰一號**,但`Attribute` 仍是**勇者一號** 使用屬性繫節也會得到相同結果 ```html= <input type="text" value="勇者一號" [value]="'勇者一號'"> ``` 這裡只能透過Javascript的 `setAttribute()` 手段來修改HTML Attribute