組件間通信

enter image description here

組件就像零散的積木识脆,我們需要把這些積木按照一定的規(guī)則拼裝起來甸祭,而且要讓它們互相之間能進(jìn)行通訊缕碎,這樣才能構(gòu)成一個(gè)有機(jī)的完整系統(tǒng)。
在真實(shí)的應(yīng)用中池户,組件最終會(huì)構(gòu)成樹形結(jié)構(gòu)咏雌,就像人類社會(huì)中的家族樹一樣:


enter image description here

在樹形結(jié)構(gòu)里面凡怎,組件之間有幾種典型的關(guān)系:父子關(guān)系、兄弟關(guān)系处嫌、沒有直接關(guān)系栅贴。
相應(yīng)地斟湃,組件之間有以下幾種典型的通訊方案:

直接的父子關(guān)系:父組件直接訪問子組件的 public 屬性和方法熏迹。
直接的父子關(guān)系:借助于 @Input 和 @Output 進(jìn)行通訊
沒有直接關(guān)系:借助于 Service 單例進(jìn)行通訊。
利用 cookie 和 localstorage 進(jìn)行通訊凝赛。
利用 session 進(jìn)行通訊注暗。

無論你使用什么前端框架,組件之間的通訊都離開不以上幾種方案墓猎,這些方案與具體框架無關(guān)捆昏。

直接調(diào)用

對于有直接父子關(guān)系的組件,父組件可以直接訪問子組件里面 public 型的屬性和方法毙沾,示例代碼片段如下:

<child #child></child>
<button (click)="child.childFn()" class="btn btn-success">調(diào)用子組件方法</button>

顯然骗卜,子組件里面必須暴露一個(gè) public 型的 childFn 方法,就像這樣:
public childFn():void{ console.log("子組件的名字是>"+this.panelTitle);}
以上是通過在模板里面定義局部變量的方式來直接調(diào)用子組件里面的 public 型方法左胞。在父組件的內(nèi)部也可以訪問到子組件的實(shí)例寇仓,需要利用到 @ViewChild 裝飾器,示例如下:
@ViewChild(ChildComponent)private childComponent: ChildComponent;
關(guān)于 @ViewChild 在后面的內(nèi)容里面會(huì)有更詳細(xì)的解釋烤宙。
很明顯遍烦,如果父組件直接訪問子組件,那么兩個(gè)組件之間的關(guān)系就被固定死了躺枕。父子兩個(gè)組件緊密依賴服猪,誰也離不開誰,也就都不能單獨(dú)使用了拐云。所以罢猪,除非你知道自己在做什么,最好不要直接在父組件里面直接訪問子組件上的屬性和方法叉瘩,以免未來一改一大片膳帕。

@Input 和 @Output

我們可以利用 @Input 裝飾器,讓父組件直接給子組件傳遞參數(shù)房揭,子組件上這樣寫:
@Input()public panelTitle:string;
父組件上可以這樣設(shè)置 panelTitle 這個(gè)參數(shù):
<child panelTitle="一個(gè)新的標(biāo)題"></child>
@Output 的本質(zhì)是事件機(jī)制备闲,我們可以利用它來監(jiān)聽子組件上派發(fā)的事件,子組件上這樣寫:
@Output()public follow=new EventEmitter();

觸發(fā) follow 事件的方式如下:
this.follow.emit("follow");
父組件上可以這樣監(jiān)聽 follow 事件:
<child (follow)="doSomething()"></child>
我們可以利用 @Output 來自定義事件捅暴,監(jiān)聽自定義事件的方式也是通過小圓括號恬砂,與監(jiān)聽 HTML 原生事件的方式一模一樣。

利用 Service 單例進(jìn)行通訊

enter image description here

如果你在根模塊(一般是 app.module.ts)的 providers 里面注冊一個(gè) Service蓬痒,那么這個(gè) Service 就是全局單例的泻骤,這樣一來我們就可以利用這個(gè)單例的 Service 在不同的組件之間進(jìn)行通訊了。

  • 比較粗暴的方式:我們可以在 Service 里面定義 public 型的共享變量,然后讓不同的組件都來訪問這塊變量狱掂,從而達(dá)到共享數(shù)據(jù)的目的演痒。
  • 優(yōu)雅一點(diǎn)的方式:利用 RxJS,在 Service 里面定義一個(gè) public 型的 Subject(主題)趋惨,然后讓所有組件都來subscribe(訂閱)這個(gè)主題鸟顺,類似于一種“事件總線”的效果。

實(shí)例代碼片段:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';

/**
 * 用來充當(dāng)事件總線的Service
 */
@Injectable()
export class EventBusService {
  public eventBus:Subject = new Subject();

  constructor() { }

}
import { Component, OnInit } from '@angular/core';
import { EventBusService } from '../service/event-bus.service';

@Component({
  selector: 'child-1',
  templateUrl: './child-1.component.html',
  styleUrls: ['./child-1.component.css']
})
export class Child1Component implements OnInit {

  constructor(public eventBusService:EventBusService) { }

  ngOnInit() {
  }

  public triggerEventBus():void{
    this.eventBusService.eventBus.next("第一個(gè)組件觸發(fā)的事件");
  }
}
import { Component, OnInit } from '@angular/core';
import { EventBusService } from '../service/event-bus.service';

@Component({
  selector: 'child-2',
  templateUrl: './child-2.component.html',
  styleUrls: ['./child-2.component.css']
})
export class Child2Component implements OnInit {
  public events:Array=[];

  constructor(public eventBusService:EventBusService) {

  }

  ngOnInit() {
    this.eventBusService.eventBus.subscribe((value)=>{
      this.events.push(value+"-"+new Date());
    });
  }
}

利用 cookie 或者 localstorage 進(jìn)行通訊

enter image description here

示例代碼片段:

public writeData():void{
    window.localStorage.setItem("json",JSON.stringify({name:'大漠窮秋',age:18}));
}
var json=window.localStorage.getItem("json");
// window.localStorage.removeItem("json");
var obj=JSON.parse(json);
console.log(obj.name);
console.log(obj.age);

很多朋友寫 Angular 代碼的時(shí)候出現(xiàn)了思維定勢器虾,總感覺 Angular 會(huì)封裝所有東西讯嫂,實(shí)際上并非如此。比如 cookie兆沙、localstorage 這些東西都可以直接用原生的 API 進(jìn)行操作的欧芽。千萬別忘記原生的那些 API 啊,都能用的葛圃!

利用 session 進(jìn)行通訊

enter image description here

小結(jié)
組件間的通訊方案是通用的千扔,無論你使用什么樣的前端框架,都會(huì)面臨這個(gè)問題库正,而解決的方案無外乎本文所列出的幾種曲楚。
本節(jié)完整可運(yùn)行的實(shí)例代碼請參見這里 請檢出 communication 分支。

大漠原文 诀诊,請付費(fèi)支持http://gitbook.cn/gitchat/column/59dae2081e6d652a5a9c3603/topic/59dc78a41e6d652a5a9c7aa3#writeCommentDiv

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末洞渤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子属瓣,更是在濱河造成了極大的恐慌载迄,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抡蛙,死亡現(xiàn)場離奇詭異护昧,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)粗截,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門惋耙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人熊昌,你說我怎么就攤上這事绽榛。” “怎么了婿屹?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵灭美,是天一觀的道長。 經(jīng)常有香客問我昂利,道長届腐,這世上最難降的妖魔是什么铁坎? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮犁苏,結(jié)果婚禮上硬萍,老公的妹妹穿的比我還像新娘。我一直安慰自己围详,他們只是感情好朴乖,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著短曾,像睡著了一般欧聘。 火紅的嫁衣襯著肌膚如雪抗果。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天税娜,我揣著相機(jī)與錄音魁兼,去河邊找鬼婉徘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛咐汞,可吹牛的內(nèi)容都是我干的盖呼。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼化撕,長吁一口氣:“原來是場噩夢啊……” “哼几晤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起植阴,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤蟹瘾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后掠手,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體憾朴,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年喷鸽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了众雷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡做祝,死狀恐怖砾省,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情混槐,我是刑警寧澤编兄,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站纵隔,受9級特大地震影響翻诉,放射性物質(zhì)發(fā)生泄漏炮姨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一碰煌、第九天 我趴在偏房一處隱蔽的房頂上張望舒岸。 院中可真熱鬧,春花似錦芦圾、人聲如沸蛾派。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洪乍。三九已至,卻和暖如春夜焦,著一層夾襖步出監(jiān)牢的瞬間壳澳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工茫经, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留巷波,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓卸伞,卻偏偏與公主長得像抹镊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子荤傲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

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

  • 前言 組件是 vue.js最強(qiáng)大的功能之一垮耳,而組件實(shí)例的作用域是相互獨(dú)立的,這就意味著不同組件之間的數(shù)據(jù)無法相互引...
    浪里行舟閱讀 8,230評論 0 49
  • 前言 組件是 vue.js最強(qiáng)大的功能之一遂黍,而組件實(shí)例的作用域是相互獨(dú)立的终佛,這就意味著不同組件之間的數(shù)據(jù)無法相互引...
    用技術(shù)改變世界閱讀 2,154評論 1 3
  • 摘要: 總有一款合適的通信方式。 作者:浪里行舟 Fundebug經(jīng)授權(quán)轉(zhuǎn)載妓湘,版權(quán)歸原作者所有查蓉。 前言 組件是 v...
    Fundebug閱讀 15,573評論 3 57
  • 前言 組件是 vue.js最強(qiáng)大的功能之一,而組件實(shí)例的作用域是相互獨(dú)立的榜贴,這就意味著不同組件之間的數(shù)據(jù)無法相互引...
    Vicky丶Amor閱讀 5,988評論 10 162
  • 前言 組件是 vue.js最強(qiáng)大的功能之一豌研,而組件實(shí)例的作用域是相互獨(dú)立的,這就意味著不同組件之間的數(shù)據(jù)無法相互引...
    7abbcd54a89d閱讀 707評論 0 1