Angular2 組件通信的實(shí)例代碼
1. 組件通信
我們知道Angular2應(yīng)用程序?qū)嶋H上是有很多父子組價(jià)組成的組件樹(shù),因此,了解組件之間如何通信,特別是父子組件之間,對(duì)編寫Angular2應(yīng)用程序具有十分重要的意義,通常來(lái)講,組件之間的交互方式主要有如下幾種:
- 使用輸入型綁定,把數(shù)據(jù)從父組件傳到子組件
- 通過(guò) setter 攔截輸入屬性值的變化
- 使用 ngOnChanges 攔截輸入屬性值的變化
- 父組件監(jiān)聽(tīng)子組件的事件
- 父組件與子組件通過(guò)本地變量互動(dòng)
- 父組件調(diào)用 ViewChild
- 父組件和子組件通過(guò)服務(wù)來(lái)通訊
本文會(huì)通過(guò)講解著幾種方式來(lái)對(duì)組件之間的通信做一個(gè)大致的介紹。
2. 輸入型綁定
輸入型綁定指的是利用模板語(yǔ)法中的屬性型綁定方式,將父組件的數(shù)據(jù)傳遞到子組件對(duì)應(yīng)的對(duì)象中,子組件中的對(duì)象一般使用@Input裝飾器來(lái)修飾,作為數(shù)據(jù)的接受者,例如
@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"; } }
以上的例子我們可以看出,存在父子兩個(gè)組件,在父組件ParentComponent中的模板中引入了<child [input]="data"></child>子組件,并將data數(shù)據(jù)通過(guò)屬性綁定的方式綁定到input屬性中傳入到子組件中,子組件中通過(guò)@Input()注解修飾input屬性來(lái)接收傳入的數(shù)據(jù),并顯示在模板I am fron {{input}}中。
輸入型綁定是從父組件傳遞數(shù)據(jù)到子組件最常見(jiàn)的方式。
3. setter監(jiān)聽(tīng)
我們知道,Angular2是一個(gè)MVVM的框架,當(dāng)數(shù)據(jù)發(fā)生變化時(shí)能夠同步顯示到模板視圖中,可以使用一個(gè)輸入屬性的 setter 函數(shù),以攔截父組件中值的變化,并采取行動(dòng)。例如,我們改造上面的例子,子組件中使用set,get重寫對(duì)應(yīng)的綁定input屬性,當(dāng)輸入值方式變化時(shí)輸出一個(gè)控制臺(tái)信息。
@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
除了上面說(shuō)的setter函數(shù)可以響應(yīng)輸入數(shù)據(jù)的變化外,Angular2還提供了一個(gè)生命周期函數(shù)ngOnChanges 可以監(jiān)聽(tīng)數(shù)據(jù)的變化。使用 OnChanges 生命周期鉤子接口的 ngOnChanges 方法來(lái)監(jiān)測(cè)輸入屬性值的變化并做出回應(yīng)。我們改造以上的子組件來(lái)響應(yīng)對(duì)應(yīng)的變化,在這個(gè)示例中,我們監(jiān)聽(tīng)了輸入數(shù)據(jù)的變化,采取的對(duì)應(yīng)動(dòng)作僅僅是輸出對(duì)應(yīng)的信息,當(dāng)然你也可以做很多其他的事情。
@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. 事件傳播
上面的集中方式都是父組件如何向子組件傳遞數(shù)據(jù)以及子組件如何監(jiān)聽(tīng)數(shù)據(jù)的變化,事件傳播則是子組件如何向父組件通信的一種方式。子組件暴露一個(gè) EventEmitter 屬性,當(dāng)事件發(fā)生時(shí),子組件利用該屬性 emits( 向上彈射 ) 事件。父組件綁定到這個(gè)事件屬性,并在事件發(fā)生時(shí)作出回應(yīng)。子組件的 EventEmitter 屬性是一個(gè) 輸出屬性 ,通常帶有 @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); } }
在上面的例子中,我們?cè)谧咏M件ChildComponent添加了一個(gè)向外傳播的事件output:EventEmitter<string> = new EventEmitter<string>(),并添加了一個(gè)點(diǎn)擊的按鈕,當(dāng)按鈕事件觸發(fā)時(shí),就會(huì)調(diào)用output事件向父組件傳遞事件,并將數(shù)據(jù)作為參數(shù)傳遞到父組件ParentComponent中,同時(shí)在父組件ParentComponent的模板<child [input]="data" (output)="output($event)"></child>中可以看到,我們使用模板語(yǔ)法中的事件綁定,綁定了output函數(shù)作為對(duì)應(yīng)事件的接受函數(shù),當(dāng)子組件output事件觸發(fā)是,父組件的函數(shù)就會(huì)得到執(zhí)行。
使用事件傳播來(lái)進(jìn)行子組件對(duì)父組件之間的通信是最常見(jiàn)的方式。
6. 本地變量
在模板語(yǔ)法中,我們知道存在著本地變量這種語(yǔ)法,可以使用本地變量來(lái)代表對(duì)應(yīng)的組件。雖然父組件不能使用數(shù)據(jù)綁定來(lái)讀取子組件的屬性或調(diào)用子組件的方法。但可以在父組件模板里,新建一個(gè)本地變量來(lái)代表子組件,然后利用這個(gè)變量來(lái)讀取子組件的屬性和調(diào)用子組件的方法,不過(guò)這種使用方式只能在模板中使用,例如如下所示,改寫上面例子中的父組件模板,代碼如下。
我們?cè)赑arentComponent組件中使用本地變量#child獲取了child組件的實(shí)例,這樣就可以在模板中使用其屬性或者方法,例如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
本地變量的方式是在父組件的模板中獲取子組件的實(shí)例,有木有其他方式可以在組件的類中獲取子組件的實(shí)例呢?答案是肯定的,如果父組件的類需要讀取子組件的屬性值或調(diào)用子組件的方法,就不能使用本地變量方法。當(dāng)父組件類 需要這種訪問(wèn)時(shí),可以把子組件作為ViewChild,注入到父組件里面。例如,我們改造上面的父組件的組件類,使用ViewChild來(lái)獲取子組件的實(shí)例,代碼如下:
@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)注解的形式獲取了對(duì)應(yīng)子組件childComponent的實(shí)例,這樣在父組件類中就可以調(diào)用子組件對(duì)應(yīng)的屬性及方法了。
相對(duì)于本地變量的方式而言,ViewChild的方式更加靈活,用途也比較廣泛。但是,需要注意的一點(diǎn)是,必須等待父組件的視圖顯示完成后才可以使用,因此,ngAfterViewInit 生命周期鉤子是非常重要的一步。
8. 服務(wù)方式
通過(guò)服務(wù)依賴注入的方式,我們可以了解到,服務(wù)在父子組件之間是可以共享的,因此,我們可以利用共享的服務(wù)的形式在父子組件之間進(jìn)行通信。
如果我們將服務(wù)實(shí)例的作用域被限制在父組件和其子組件內(nèi),這個(gè)組件子樹(shù)之外的組件將無(wú)法訪問(wèn)該服務(wù)或者與它們通訊。
一般來(lái)說(shuō),父子之間使用服務(wù)的方式來(lái)通行,是采用事件消息的形式來(lái)實(shí)現(xiàn)的。
例如,如下的代碼中,父子組件共享了Service服務(wù),并在各自的類中獲取了Service服務(wù)的實(shí)例,當(dāng)分別點(diǎn)擊父子組件中的按鈕時(shí),就能夠觸發(fā)Service服務(wù)中的對(duì)應(yīng)的input$以及output$,因?yàn)榉?wù)是共享的,所以在父子組件中監(jiān)聽(tīng)對(duì)應(yīng)的服務(wù)信息,就能夠得到傳遞的消息。
@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'); } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
AngularJS 應(yīng)用身份認(rèn)證的技巧總結(jié)
這篇文章主要介紹了AngularJS 應(yīng)用身份認(rèn)證的技巧總結(jié),具有一定的參考價(jià)值,有需要的可以了解一下。2016-11-11angularJs中$http獲取后臺(tái)數(shù)據(jù)的實(shí)例講解
今天小編就為大家分享一篇angularJs中$http獲取后臺(tái)數(shù)據(jù)的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08AngularJs入門教程之環(huán)境搭建+創(chuàng)建應(yīng)用示例
這篇文章主要介紹了AngularJs入門教程之環(huán)境搭建+創(chuàng)建應(yīng)用的方法,較為詳細(xì)的分析了AngularJS的功能、下載及應(yīng)用創(chuàng)建方法,需要的朋友可以參考下2016-11-11AngularJS實(shí)現(xiàn)星星等級(jí)評(píng)分功能
這篇文章主要為大家詳細(xì)介紹了AngularJS實(shí)現(xiàn)星星等級(jí)評(píng)分功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09AngularJs Using $location詳解及示例代碼
本文主要介紹AngularJs Using $location的知識(shí)資料,這里整理了相關(guān)的資料,及簡(jiǎn)單示例代碼,有興趣的小伙伴可以參考下2016-09-09angularjs請(qǐng)求數(shù)據(jù)的方法示例
這篇文章主要給大家介紹了關(guān)于angularjs請(qǐng)求數(shù)據(jù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用angularjs具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08淺談Angular2 ng-content 指令在組件中嵌入內(nèi)容
本篇文章主要介紹了淺談Angular2 ng-content 指令在組件中嵌入內(nèi)容,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08angularjs實(shí)現(xiàn)多張圖片上傳并預(yù)覽功能
這篇文章主要為大家詳細(xì)介紹了angularjs實(shí)現(xiàn)多張圖片上傳并預(yù)覽功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02Angular.JS中指令ng-if、ng-show/ng-hide和ng-switch的使用教程
在Angular的原生指令中有這幾個(gè)指令用來(lái)控制元素的展示與否,ng-show/ng-hide/ng-if和ng-switch。在angular性能優(yōu)化中,我們也常常會(huì)用到它。這篇文章主要給大家介紹了在Angular.JS中指令ng-if、ng-show/ng-hide和ng-switch的使用教程,需要的朋友可以參考。2017-05-05Angular實(shí)現(xiàn)類似博客評(píng)論的遞歸顯示及獲取回復(fù)評(píng)論的數(shù)據(jù)
這篇文章主要給大家介紹了關(guān)于Angular如何實(shí)現(xiàn)類似博客評(píng)論的遞歸顯示及獲取回復(fù)評(píng)論的數(shù)據(jù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11