更新時間 - 2017-03-22html
Input 是屬性裝飾器,用來定義組件內的輸入屬性。在實際應用場合,咱們主要用來實現父組件向子組件傳遞數據。Angular 應用是由各式各樣的組件組成,當應用啓動時,Angular 會從根組件開始啓動,並解析整棵組件樹,數據由上而下流下下一級子組件。typescript
counter.component.tssegmentfault
import { Component, Input } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>當前值: {{ count }}</p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent { @Input() count: number = 0; increment() { this.count++; } decrement() { this.count--; } }
app.component.ts瀏覽器
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <exe-counter [count]="initialCount"></exe-counter> ` }) export class AppComponent { initialCount: number = 5; }
以上代碼運行後瀏覽器顯示的結果:app
Input 裝飾器支持一個可選的參數,用來指定組件綁定屬性的名稱。若是沒有指定,則默認使用 @Input 裝飾器,裝飾的屬性名。具體示例以下:ide
counter.component.ts函數
import { Component, Input } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>當前值: {{ count }}</p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent { @Input('value') count: number = 0; ... // 其他代碼未改變 }
app.component.tsui
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <exe-counter [value]="initialCount"></exe-counter> ` }) export class AppComponent { initialCount: number = 5; }
import { Component, Input } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>當前值: {{ count }}</p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> `, inputs:['count:value'] // 類成員屬性名稱:綁定的輸入屬性名稱 }) export class CounterComponent { count: number = 0; increment() { this.count++; } decrement() { this.count--; } }
setter 和 getter 是用來約束屬性的設置和獲取,它們提供了一些屬性讀寫的封裝,可讓代碼更便捷,更具可擴展性。經過 setter 和 getter 方式,咱們對類中的私有屬性進行了封裝,能避免外界操做影響到該私有屬性。此外經過 setter 咱們還能夠封裝一些業務邏輯,具體示例以下:this
counter.component.tsspa
import { Component, Input } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>當前值: {{ count }} </p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent { _count: number = 0; // 默認私有屬性如下劃線開頭,不是必須也可使用$count biggerThanTen: boolean = false; @Input() set count (num: number) { this.biggerThanTen = num > 10; this._count = num; } get count(): number { return this._count; } increment() { this.count++; } decrement() { this.count--; } }
當數據綁定輸入屬性的值發生變化的時候,Angular 將會主動調用 ngOnChanges 方法。它會得到一個 SimpleChanges 對象,包含綁定屬性的新值和舊值,它主要用於監測組件輸入屬性的變化。具體示例以下:
import { Component, Input, SimpleChanges, OnChanges } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>當前值: {{ count }}</p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent implements OnChanges{ @Input() count: number = 0; ngOnChanges(changes: SimpleChanges) { console.dir(changes['count']); } increment() { this.count++; } decrement() { this.count--; } }
以上代碼運行後瀏覽器顯示的結果:
上面例子中須要注意的是,當手動改變輸入屬性的值,是不會觸發 ngOnChanges
鉤子的。
1.在構造函數中是獲取不到輸入屬性的值
在子組件的構造函數中,是沒法獲取輸入屬性的值,只能在 ngOnChanges 或 ngOnInit 鉤子中獲取到。由於子組件的構造函數會優先執行,當子組件輸入屬性變化時會自動調用 ngOnChanges 鉤子,而後在調用 ngOnInit 鉤子,因此在 ngOnInit 鉤子內能獲取到輸入的屬性。
具體詳情可參考 - Angular 2 constructor & ngOnInit
2.不能同時使用 @Input 裝飾器 或在 @Directive、@Component inputs 字段中定義同一個輸入屬性,具體示例以下:
@Component({ selector: 'exe-counter', inputs:['count:value'] }) export class CounterComponent { @Input('value') count: number = 0; }
3.@Input vs inputs
相同點:
它們都是用來定義輸入屬性
異同點:
inputs 定義在指令的 metadata 信息中,開發者對指令的輸入屬性一目瞭然。此外對於未選用 TypeScript 做爲開發語言的開發者,也只能在 metadata 中定義指令的輸入屬性。
@Input 屬於屬性裝飾器,經過它咱們能夠一塊兒定義屬性的訪問描述符 (public、private、protected):
@Input() public attr: string;
4.輸入、輸出屬性風格指南
4.1 堅持使用 @Input 和 @Output ,而非 @Directive 和 @Component 裝飾器的 inputs 和 outputs 屬性:
易於在類裏面識別哪些屬性是輸入屬性或輸出屬性。
4.2 堅持把 @Input 或者 @Output 放到所裝飾的屬性的同一行:
若是須要重命名與@Input
或者@Output
關聯的屬性或事件名,你能夠在一個位置修改。
4.3 避免爲輸入和輸出屬性指定別名
同一個屬性有兩個名字(一個對內一個對外)很容易致使混淆。
詳細信息請參考 - Angular 2 風格指南 - STYLE 05-12
5.項目開發中儘可能經過 @Input 裝飾器定義無狀態的組件,即組件僅依賴於輸入屬性,這樣會大大提升組件可複用性