Angular2 組件通訊

原文:http://www.cnblogs.com/SLchuck/p/5904000.html

1. 組件通訊

咱們知道Angular2應用程序其實是有不少父子組價組成的組件樹,所以,瞭解組件之間如何通訊,特別是父子組件之間,對編寫Angular2應用程序具備十分重要的意義,一般來說,組件之間的交互方式主要有以下幾種:html

l 使用輸入型綁定,把數據從父組件傳到子組件框架

l 經過 setter 攔截輸入屬性值的變化ide

l 使用 ngOnChanges 攔截輸入屬性值的變化函數

l 父組件監聽子組件的事件this

l 父組件與子組件經過本地變量互動spa

l 父組件調用 ViewChildhtm

l 父組件和子組件經過服務來通信對象

本文會經過講解着幾種方式來對組件之間的通訊作一個大體的介紹。blog

2. 輸入型綁定

輸入型綁定指的是利用模板語法中的屬性型綁定方式,將父組件的數據傳遞到子組件對應的對象中,子組件中的對象通常使用@Input裝飾器來修飾,做爲數據的接受者,例如接口

@Component({

selector: 'child',

template: 'I am fron {{input}}'

})

export class ChildComponent implements OnInit {

@Input()

input;

constructor() { }

ngOnInit() { }

}

@Component({

selector: 'parent',

template: '<child [input]="data"></child>'

})

export class ParentComponent implements OnInit {

data: string;

constructor() { }

ngOnInit() {

this.data = "parent";

}

}

以上的例子咱們能夠看出,存在父子兩個組件,在父組件ParentComponent中的模板中引入了<child [input]="data"></child>子組件,並將data數據經過屬性綁定的方式綁定到input屬性中傳入到子組件中,子組件中經過@Input()註解修飾input屬性來接收傳入的數據,並顯示在模板I am fron {{input}}中。

輸入型綁定是從父組件傳遞數據到子組件最多見的方式。

3. setter監聽

咱們知道,Angular2是一個MVVM的框架,當數據發生變化時可以同步顯示到模板視圖中,可使用一個輸入屬性的 setter 函數,以攔截父組件中值的變化,並採起行動。例如,咱們改造上面的例子,子組件中使用set,get重寫對應的綁定input屬性,當輸入值方式變化時輸出一個控制檯信息。

@Component({

selector: 'child',

template: 'I am fron {{data}}'

})

export class ChildComponent implements OnInit {

_input:string;

@Input()

public set input(v : string) {

this._input = v;

console.log(v);

}

public get input() : string {

return this._input;

}

constructor() { }

ngOnInit() { }

}

4. ngOnChanges

除了上面說的setter函數能夠響應輸入數據的變化外,Angular2還提供了一個生命週期函數ngOnChanges 能夠監聽數據的變化。使用 OnChanges 生命週期鉤子接口的 ngOnChanges 方法來監測輸入屬性值的變化並作出迴應。咱們改造以上的子組件來響應對應的變化,在這個示例中,咱們監聽了輸入數據的變化,採起的對應動做僅僅是輸出對應的信息,固然你也能夠作不少其餘的事情。

@Component({

selector: 'child',

template: 'I am fron {{data}}'

})

export class ChildComponent implements OnInit, OnChanges {

_input: string;

@Input()

public set input(v: string) {

this._input = v;

console.log(v);

}

public get input(): string {

return this._input;

}

constructor() { }

ngOnInit() { }

ngOnChanges(changes: SimpleChanges) {

console.log(changes);

}

}

5. 事件傳播

上面的集中方式都是父組件如何向子組件傳遞數據以及子組件如何監聽數據的變化,事件傳播則是子組件如何向父組件通訊的一種方式。子組件暴露一個 EventEmitter 屬性,當事件發生時,子組件利用該屬性 emits( 向上彈射 ) 事件。父組件綁定到這個事件屬性,並在事件發生時做出迴應。子組件的 EventEmitter 屬性是一個 輸出屬性 ,一般帶有 @Output 裝飾器 。

@Component({

selector: 'child',

template: `

I am fron {{data}}<br />

<button id="out" (click)="click()">click for out</button>

`

})

export class ChildComponent implements OnInit, OnChanges {

_input: string;

@Input()

public set input(v: string) {

this._input = v;

console.log(v);

}

public get input(): string {

return this._input;

}

@Output()

output:EventEmitter<string> = new EventEmitter<string>();

click(){

this.output.emit("i am from child");

}

constructor() { }

ngOnInit() { }

ngOnChanges(changes: SimpleChanges) {

console.log(changes);

}

}

@Component({

selector: 'parent',

template: '<child [input]="data" (output)="output($event)"></child>'

})

export class ParentComponent implements OnInit {

data: string;

constructor() { }

ngOnInit() {

this.data = "parent";

}

output($event){

console.log($event);

}

}

在上面的例子中,咱們在子組件ChildComponent添加了一個向外傳播的事件output:EventEmitter<string> = new EventEmitter<string>(),並添加了一個點擊的按鈕,當按鈕事件觸發時,就會調用output事件向父組件傳遞事件,並將數據做爲參數傳遞到父組件ParentComponent中,同時在父組件ParentComponent的模板<child [input]="data" (output)="output($event)"></child>中能夠看到,咱們使用模板語法中的事件綁定,綁定了output函數做爲對應事件的接受函數,當子組件output事件觸發是,父組件的函數就會獲得執行。

使用事件傳播來進行子組件對父組件之間的通訊是最多見的方式。

6. 本地變量

在模板語法中,咱們知道存在着本地變量這種語法,可使用本地變量來表明對應的組件。雖然父組件不能使用數據綁定來讀取子組件的屬性或調用子組件的方法。但能夠在父組件模板裏,新建一個本地變量來表明子組件,而後利用這個變量來讀取子組件的屬性和調用子組件的方法,不過這種使用方式只能在模板中使用,例如以下所示,改寫上面例子中的父組件模板,代碼以下。

咱們在ParentComponent組件中使用本地變量#child獲取了child組件的實例,這樣就能夠在模板中使用其屬性或者方法,例如child.input。

@Component({

selector: 'parent',

template: '<child [input]="data" (output)="output($event)" #child></child>{{child.input}}'

})

export class ParentComponent implements OnInit {

data: string;

constructor() { }

ngOnInit() {

this.data = "parent";

}

output($event){

console.log($event);

}

}

7. ViewChild

本地變量的方式是在父組件的模板中獲取子組件的實例,有木有其餘方式能夠在組件的類中獲取子組件的實例呢?答案是確定的,若是父組件的類須要讀取子組件的屬性值或調用子組件的方法,就不能使用本地變量方法。當父組件類 須要這種訪問時,能夠把子組件做爲ViewChild,注入到父組件裏面。例如,咱們改造上面的父組件的組件類,使用ViewChild來獲取子組件的實例,代碼以下:

@Component({

selector: 'parent',

template: '<child [input]="data" (output)="output($event)" #child></child>{{child.input}}'

})

export class ParentComponent implements OnInit {

@ViewChild(ChildComponent)

private childComponent: ChildComponent;

data: string;

constructor() { }

ngOnInit() {

this.data = "parent";

}

output($event) {

console.log($event);

}

}

在以上的代碼中,咱們使用@ViewChild(ChildComponent)註解的形式獲取了對應子組件childComponent的實例,這樣在父組件類中就能夠調用子組件對應的屬性及方法了。

相對於本地變量的方式而言,ViewChild的方式更加靈活,用途也比較普遍。可是,須要注意的一點是,必須等待父組件的視圖顯示完成後纔可使用,所以,ngAfterViewInit 生命週期鉤子是很是重要的一步。

8. 服務方式

經過服務依賴注入的方式,咱們能夠了解到,服務在父子組件之間是能夠共享的,所以,咱們能夠利用共享的服務的形式在父子組件之間進行通訊。

若是咱們將服務實例的做用域被限制在父組件和其子組件內,這個組件子樹以外的組件將沒法訪問該服務或者與它們通信。

通常來講,父子之間使用服務的方式來通行,是採用事件消息的形式來實現的。

例如,以下的代碼中,父子組件中共享了Service服務,並在各自的類中獲取了Service服務的實例,當分別點擊父子組件中的按鈕時,就可以觸發Service服務中的對應的input$以及output$,由於服務是共享的,因此在父子組件中監聽對應的服務信息,就可以獲得傳遞的消息。

@Injectable()

export class Service {

input$: EventEmitter<string> = new EventEmitter<string>();

output$: EventEmitter<string> = new EventEmitter<string>();

constructor() {

}

}

@Component({

selector: 'child',

template: `

<button id="out" (click)="click()">click for output</button>

`

})

export class ChildComponent {

constructor(private _service: Service) {

this._service.input$.subscribe(function (input: string) {

console.log(input);

})

}

click() {

this._service.output$.emit('i am from child');

}

}

@Component({

selector: 'parent',

template: '<child></child><button id="input" (click)="click()">click for input</button>',

providers: [Service]

})

export class ParentComponent {

constructor(private _service: Service) {

this._service.output$.subscribe(function (output: string) {

console.log(output);

})

}

click() {

this._service.input$.emit('i am from child');

}

}

相關文章
相關標籤/搜索