iT邦幫忙

2022 iThome 鐵人賽

DAY 10
0
Modern Web

Angular牙起來系列 第 10

# Day10 Angular牙起來 - 程式面介紹 繫結綁定4 雙向繫結

  • 分享至 

  • xImage
  •  

Day10 Angular牙起來 - 程式面介紹 繫結綁定4 雙向繫結

再次回到角色區塊

我們在遊戲專案中,加入金錢元素

role.component.ts 加上 money 成員變數

...

export class RoleComponent implements OnInit {
  name = '初心冒險者';
  hp = 5;
  atk = 1;
  money = 0;

...

今天我想讓玩家自己能手動輸入自己擁有的錢

並修改 role.component.html

<h2>角色區塊</h2>
<div>名稱: {{name}}</div>
<div>血量: {{hp}}</div>
<div>攻擊力: {{atk}} <button (click)="addAtk()">點我增加攻擊力</button></div>
<div>金錢: {{money}} </div>
<input type="text" placeholder="自己的錢請自己輸入">

結果畫面

使用其他方式

這個功能可以純粹透過前面章節的事件繫結來達成
這邊使用(input)事件,當輸入框偵測到任何輸入都會觸發
同時要帶入$event 事件參數,$event 是詳細描述此次事件之各種數值的物件

有幾種Evnet方式可以玩看看

(input): 偵測任何輸入時觸發
(keyup): 離開鍵盤按鍵時觸發
(blur): 焦點(當前鼠標或鍵盤聚焦之處)離開輸入框時觸發
(change): 焦點離開輸入框、並且值被改變時才觸發

修改 role.component.html

<h2>角色區塊</h2>
<div>名稱: {{name}}</div>
<div>血量: {{hp}}</div>
<div>攻擊力: {{atk}} <button (click)="addAtk()">點我增加攻擊力</button></div>
<div>金錢: {{money}} </div>
<input type="text" placeholder="自己的錢請自己輸入" (input)="changeMoney1($event)" >

role.component.ts 中增加 changeMoney1changeMoney2 方法
並且接收 event 事件參數

changeMoney1 可以換成 changeMoney2 試試看效果

修改 role.component.ts

...

export class RoleComponent implements OnInit {
...

  changeMoney1(event: any) {
    this.money = event.target.value;
  }

  changeMoney2(event: Event) {
    let value = (event.target as HTMLInputElement).value;
    this.money = Number(value);
  }

}
  • changeMoney1 是用Javascript的作法取得輸入框的欄位值,因為是any型別,Typescript不會對此做型別檢查
  • changeMoney2 作法是將Event事件,轉型成Typescript裡的物件類別HTMLInputElement再做取值,最後轉型成數字

完成畫面

不過,其實有更簡潔的方法可以達成這樣的功能

ngModel 雙向繫結

使用 [(ngModel)]="money" 也能得到相同效果
並且更加精簡,在ts程式碼完全不需要 changeMoney1changeMoney2 方法

<h2>角色區塊</h2>
<div>名稱: {{name}}</div>
<div>血量: {{hp}}</div>
<div>攻擊力: {{atk}} <button (click)="addAtk()">點我增加攻擊力</button></div>
<div>金錢: {{money}} </div>
<input type="text" placeholder="自己的錢請自己輸入" [(ngModel)]="money" >

若使用到ngModel,要在Module模組底下 app.module.ts 新增 FormsModule

因為ngModel是隸屬於FormsModule模組下的套件,所以要import進來

為什麼ngModel隸屬在FormsModule底下?
因為輸入值基本上是使用<input>,而<input>元素通常會是表單元件的一部份

ngModel 背後原理

[(ngModel)]="money" 同時帶了 屬性繫結[] 與 事件繫結() 兩種方式
短短的 [(ngModel)]="money" 其實代表著以下這行

[ngModel]="money" (ngModelChange)="money = $event">
  • [ngModel]="money" 是屬性繫結[],繫結對象綁定為money
  • (ngModelChange)="money = $event" 偵測到ngModel值發生變化時,事件會被觸發
    • 觸發的事件為 money = $event
    • 在此處的$eventngModel的值,是字串。而非前面的$event描述事件各項數值的物件

(ngModelChange) 是一個特殊的事件繫結
沿用了 AngularJS 的用法,他的存在一定伴隨著[ngModel]
事件觸發條件是當 ngModel 值發生 change 時才會觸發
所以才叫作ngModelChange

雙向繫結 Two-Way binding

在前幾篇提的繫結,都是單向繫結

  • 內嵌繫結{{}}把程式的值綁定到樣板,對元件而言是吐出值
  • 事件繫結 () 把樣板的值藉由事件傳遞給程式,對元件而言是接收值
  • 屬性繫結 [] 把程式的值綁定到樣板,對元件而言是吐出值

元件接收值: view target => data source
元件吐出值: view target <= data source

關於元件之間的 @Input@Output 用法,未來會再詳細介紹

雙向繫結意思是,對元件而言是接收值、也可以吐出值

因為雙向繫結同時包含 事件繫結 ()、屬性繫結 []
所以寫法是用中括號包小括號[()]表示,而中括號小括號的順序不能錯

有人說 [()] 像是 banana in the box 香蕉躺在盒子裡
但個人覺得看起來更像是 鮑魚(食用貝類),並且鮑魚可以雙向進出
純粹記憶用途,千萬別把我黃標

到這一步已經完成 77% 的Angular了


上一篇
# Day09 Angular牙起來 - 程式面介紹 繫結綁定3 中括號綁定法
下一篇
# Day11 Angular牙起來 - 元件 Component 中的設定
系列文
Angular牙起來30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言