iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 17
0

前一篇使用了 @Input,來向元件傳入變數,今天我們要用 @Output 對元件外傳出變數。
我們之前做了一個登入的功能,卻只能從 AccountManagerComponent 來控制登入及登出的狀態,這是非常不合理的。所以今天我想實作,在子元件按下 Login 時,可以傳送一個請求,更改 AccountManagerComponent 的 status。

@Output

@Output@Input 的基本概念相似,可以當成定義一個出口,送出event,所以我們一樣宣告一個變數,我命名為 loginRequest 並且在前面加上 @Output

// login.component.ts

@Output() loginRequest;

然後,我們需要初始化這個變數,我們給他一個 EventEmitter,可以當成是,這個變數會往 Component 外丟出 event:

@Output() loginRequest = new EventEmitter<any>();

<any> 這個地方要放當 EventEmitter 觸發時,要送出資料的型別,any 就是任意型別都可以。在我這個範例,只會丟出 boolean資料,所以其實填入 <boolean> 會比較嚴謹。

這邊注意在打 EventEmitter 時,由於我們這份 ts 還沒有 import 過這個模組,此時 VSCODE 會出現提示字,並且會幫我們 import。這時請注意,我們要選擇的是從 @angular/core import的 EventEmitter


操作正確的話,最上面的 import 應該會像這樣:

此時我們已經定義好對外的 @Output() 介面了,切到 account-manager.component.html,我們已經可以在 <app-login></app-login>下用 loginRequest 做 Event Binding。

<app-login [loginStatus]="status" (loginRequest)=""></app-login>

那麼我們現在來實作,從 LoginComponent 要送出的事件與資料,我先決定好我要的 function:
loginAction 負責登入,logout 負責登出。

 // login.component.ts
 
 loginAction() {
 }

 logout() {
 }

然後綁定到我們 login.component.html 裡面的兩個 button

 // login.component.html
 
<div *ngIf="!loginStatus">
    ...
    <input type="submit" value="Login" (click)="loginAction()">
    
</div>
<div *ngIf="loginStatus">
   <button (click)="logout()">Logout</button>
</div>

現在 loginAction()logout() 已經和login.component.html 內的 button 做完 Event binding,按下 button 就會分別觸發 loginAction()logout()
接者定義我按下這兩個 button 時, @Output()要送什麼資料出去。

我用剛剛宣告的 loginRequest,用 emit 這個function,發射一個 boolean 的物件。
登入時我發射 true ,登出時我發射 false。而這裡為求簡單,就不做驗證帳密相關的功能了。

 // login.component.ts
 
  loginAction() {
    this.loginRequest.emit(true);
  }
  logout() {
    this.loginRequest.emit(false);
  }

現在的 AccountManagerComponent 已經可以在 <app-login> 丟出 truefalse

// account-manager.component.html

<app-login ... (loginRequest)=""></app-login>

那我們要用一個 function 來接這個參數,或著說,當 loginRequest 發出 emit 時,我要觸發一個 function。所以我們需要在 account-manager.component.ts 中設計一個 function,被 loginRequest 觸發。

// account-manager.component.ts

 loginCheck($event) {
     this.status = $event;
 }
// account-manager.component.html

<app-login ... (loginRequest)="loginCheck($event)" ></app-login>

這邊的 $event 就會接到從 loginRequest emit 出來的 truefalse。並且直接改變 status 的登入狀態。

覺得疑惑的話,可以在 loginCheck($event) 中加入 console.log(),將 $event 印出來看看:

console.log('$event: ' + $event);

現在按下 Login、Logout 的 button ,就可以透過 @Output 發出事件,改變登入狀態的 status ,並且修改 Login、 Logout 的顯示與否了。

按下 Login:

再按下 Logout 又會回到 Login。

資料流大致上是這樣

@Input() 、@Output() Rename

還有在使用 @Input()@Output() 這兩個 Decorator 時,可以在括號中填入其他名字來 rename,就可以用 rename 過的名字進行 Property Binding。
舉例之前的 loginStatus

 @Input() loginStatus;

可以 rename 成 sss 或任何名字 :

 @Input('sss') loginStatus;

那我們就必須用 rename 過的名字 Binding:

<app-login [sss]="status"></app-login>

但這個 rename 的功能,Angular 是不推薦使用,所以還是盡量少用吧。


上一篇
# DAY 16 @Input
下一篇
# DAY 18 Service
系列文
從零開始的Angular前端開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言