一直到現在,我們用的 Component 都是長這個樣子:
<app-root></app-root>
<app-homepage></app-homepage>
<app-login></app-login>
只有用 Component 的 selector
來使用元件,卻沒有用到其他的屬性。
但如果我想要將資料傳到 Component 內,或是我有兩個或以上的 Component 要互相溝通,我可以怎麼做呢?
在 Componnent 的 template 中我們可以用各種 binding 的方式,與 ts
綁定事件、變數等等:
<input type="submit" [value]="text">
<button (click)="onClick()"> button </button>
...
但是一旦出了這個 Component後,我們就沒有 value
,也沒有 click
這些屬性可以用了,這時候我們就可以用 @Input
、@Output
來幫助我們在 Component 間傳遞資料。
那麼我現在設計兩個 Component,AccountManagerComponent
和 LoginComponent
,做一個假的簡單的登入系統。將LoginComponent
的標籤 <app-login>
放進 AccountManagerComponent
的 Template 中。目前兩個元件的關係是這樣的,我們稱之為父元件和子元件:
然後我要定義一些變數,在 account-manager.component.ts
宣告變數 status
,控制目前是登入或是登出的狀態。我自己定義登入是 true
,未登入是 false
,所以我初始化就設定為 false
:
// account-manager.component.ts
status = false;
在 login.component.ts
宣告變數 loginStatus
,用來控制 template
顯示的內容,並且在前面加上 @Input()
。其實跟一般的變數宣告一樣,只是前面加上 @Input()
這個 Decorator
而已。
// login.component.ts
@Input() loginStatus;
加上 @Input()
的這個動作,你可以想像成,為這個 Component 定義一個對外的入口、介面,父元件可以透過這個入口傳資料進來。
那記得使用 @Input()
時,要將 Input
import 進來。
這樣我們就能使用剛剛宣告的 @Input() loginStatus
來做 Property binding 了,我將 account-manager.component.ts
的 status
,用 Property binding 的方式傳進 <app-login>
的 loginStatus
。
// account-manager.component.html
<app-login [loginStatus]="status"></app-login>
當 <app-login>
透過 @Input()
接到從 loginStatus
送進來的值之後,login.component.html
就會因為 loginStatus
修改 DOM。
下面是我搭配 *ngIf
寫的簡單範例:
兩個 <div>
分別指定條件為 loginStatus
和 !loginStatus
,只會同時顯示其中一個 <div>
。
順便印出 {{loginStatus}}
。
// login.component.html
{{loginStatus}}
<div *ngIf="!loginStatus">
帳號 <input type="text"><br>
密碼 <input type="password"><br>
<input type="submit" value="Login">
</div>
<div *ngIf="loginStatus">
<button>Logout</button>
</div>
status = false;
status = true;
那麼就完成了一個父元件到子元件的資料傳遞。整個資料流大致上是這樣: