angular2 父組件和子組件通過服務(wù)來通訊

原文見我的博客
組件之間的通訊是在angular2的開發(fā)中不可避免的,但是目前官方文檔上介紹的很模糊,不夠詳細(xì),本文將結(jié)合自己的學(xué)習(xí)和實(shí)踐來把官網(wǎng)上父組件和子組件通過服務(wù)來通訊的實(shí)例程序進(jìn)行詳細(xì)的說明。
父組件和它的子組件共享同一個(gè)服務(wù),利用該服務(wù)在家庭內(nèi)部實(shí)現(xiàn)雙向通訊,子組件中的數(shù)據(jù)的更新可以通過服務(wù)通知到其他的子組件。但是該服務(wù)實(shí)例的作用域被限制在父組件和其子組件內(nèi)。這個(gè)組件子樹之外的組件將無法訪問該服務(wù)或者與它們通訊。這樣的一個(gè)可以實(shí)現(xiàn)父子組件之間的通訊的服務(wù)的寫法和普通的服務(wù)的寫法是不同的是需要在服務(wù)中增加用于通知其他組件數(shù)據(jù)有更改的代碼,這個(gè)是通過import { Subject } from ‘rxjs/Subject’來實(shí)現(xiàn)的。
Subject的介紹

什么是Subject?在RxJS中,Subject是一類特殊的Observable,它可以向多個(gè)Observer多路推送數(shù)值。普通的Observable并不具備多路推送的能力(每一個(gè)Observer都有自己獨(dú)立的執(zhí)行環(huán)境),而Subject可以共享一個(gè)執(zhí)行環(huán)境。
我們看看MissionService

import{ Injectable } from'@angular/core';
import{ Subject }    from'rxjs/Subject';
@Injectable()
exportclassMissionService {
//聲明變量 訂閱Observer,下面這個(gè)是一個(gè)可以實(shí)現(xiàn)組件之間通訊必不可少的
privatemissionAnnouncedSource =newSubject();
privatemissionConfirmedSource =newSubject();
missionAnnounced$ =this.missionAnnouncedSource.asObservable();
missionConfirmed$ =this.missionConfirmedSource.asObservable();
//當(dāng)組件或者服務(wù)中的數(shù)據(jù)有更改的時(shí)候調(diào)用這個(gè)方法即可將更改的數(shù)據(jù)推送到其他組件。
announceMission(mission: string) {
this.missionAnnouncedSource.next(mission);
}
confirmMission(astronaut: string) {
this.missionConfirmedSource.next(astronaut);
}
}

調(diào)用Subject對象的next(theValue) 方法后,Subject會(huì)向所有已經(jīng)在其上注冊的Observer多路推送數(shù)據(jù)。
現(xiàn)在我們來看看父組件

MissionControlComponent提供服務(wù)的實(shí)例,并將其共享給它的子組件(通過providers元數(shù)據(jù)數(shù)組),子組件可以通過構(gòu)造函數(shù)將該實(shí)例注入到自身。

import{ Component }          from'@angular/core';
import{ MissionService }     from'./mission.service';
@Component({
selector:'mission-control',
template: `
Mission Control
Announce mission
[astronaut]="astronaut">
History

{{event}}
`,
providers: [MissionService]
})
exportclassMissionControlComponent {
astronauts = ['Lovell','Swigert','Haise'];
history: string[] = [];
missions = ['Fly to the moon!',
'Fly to mars!',
'Fly to Vegas!'];
nextMission =0;
constructor(privatemissionService: MissionService) {
missionService.missionConfirmed$.subscribe(
astronaut => {
this.history.push(`${astronaut} confirmed the mission`);
});
}
announce() {
let mission =this.missions[this.nextMission++];
this.missionService.announceMission(mission);
this.history.push(`Mission"${mission}"announced`);
if(this.nextMission >=this.missions.length) {this.nextMission =0; }
}
}

這個(gè)例子中服務(wù)的提供者在父組件中提供的,在實(shí)際的代碼中可能會(huì)報(bào)錯(cuò),可以將服務(wù)的提供者放到app.module.ts中。父組件中我們需要關(guān)注一點(diǎn)[astronaut]=”astronaut”,這個(gè)是把子組件中的變量和父組件中的變量綁定起來。這樣astronaut的值在其中一個(gè)子組件中有更改的時(shí)候服務(wù)通知的時(shí)候就可以通知父組件和其他綁定了這個(gè)變量的子組件。
我們在看看子組件:

AstronautComponent也通過自己的構(gòu)造函數(shù)注入該服務(wù)。由于每個(gè)AstronautComponent都是MissionControlComponent的子組件,所以它們獲取到的也是父組件的這個(gè)服務(wù)實(shí)例。

import{ Component, Input, OnDestroy } from'@angular/core';
import{ MissionService } from'./mission.service';
import{ Subscription }   from'rxjs/Subscription';
@Component({
selector:'my-astronaut',
template: `
{{astronaut}}: **{{mission}}**
(click)="confirm()"
[disabled]="!announced || confirmed">
Confirm
`
})
exportclassAstronautComponentimplementsOnDestroy {
@Input() astronaut: string;
mission ='';
confirmed =false;
announced =false;
subscription: Subscription;
constructor(privatemissionService: MissionService) {
//根據(jù)自己的需要看是否需要
this.subscription = missionService.missionAnnounced$.subscribe(
mission => {
this.mission = mission;
this.announced =true;
this.confirmed =false;
});
}
//這里調(diào)用很關(guān)鍵,必須要有
confirm() {
this.confirmed =true;
this.missionService.confirmMission(this.astronaut);
}
ngOnDestroy() {
// prevent memory leak when component destroyed
this.subscription.unsubscribe();
}
}

在這個(gè)子組件中confirm方法調(diào)用了服務(wù)中的confirmMission來通知父組件astronaut的值已經(jīng)更改。注意,通過subscription服務(wù)訂閱任務(wù),并在AstronautComponent被銷毀的時(shí)候退訂。這是一個(gè)用于防止內(nèi)存泄漏的保護(hù)措施。實(shí)際上,在這個(gè)應(yīng)用程序中并沒有這個(gè)風(fēng)險(xiǎn),因?yàn)锳stronautComponent的生命期和應(yīng)用程序的生命期一樣長。但在更復(fù)雜的應(yīng)用程序環(huán)境中就不一定了。
總結(jié):angular2父組件和子組件通過服務(wù)來通訊主要有3點(diǎn)
一、在服務(wù)中使用訂閱來想各個(gè)組件推動(dòng)數(shù)據(jù);
二、在父組件的模板中綁定屬性,父子組件中的構(gòu)造函數(shù)同時(shí)使用服務(wù)參數(shù);
三、在子組件中調(diào)用服務(wù)中的推送來推送數(shù)據(jù)更改,其他子組件可以通過ngOnChanges來檢查更改然后做出相應(yīng)的處理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,837評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,820評論 25 708
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,739評論 18 399
  • 我見證過谷子的成熟 金燦太陽下的大地 果實(shí)已被收割 殘留下地的疤痕 不是痛,不是荒涼 是孩子成長的痕跡 ——長弓 ...
    郁衡子閱讀 151評論 0 0
  • 閨密青青自嘲自己曾經(jīng)是一條毛毛蟲,到哪都被忽視的那種。她是我從小的玩伴,父母離異,她跟隨父親長大,所以性格比較陽剛...
    豬囡囡閱讀 312評論 2 1