父子組件間的通信

通信方式1(單向綁定): Props down, Events up (建議使用)

Props down, Events up 是指 使用props向子組件傳遞數(shù)據(jù),父組件屬性發(fā)生變化時(shí),子組件可實(shí)時(shí)更新視圖;子組件發(fā)生變化,可以使用$emit發(fā)送事件消息,以此向父組件傳遞變化消息。

props 是單向的,當(dāng)父組件的屬性變化時(shí),將傳遞給子組件,但子組件中的props屬性變化不會(huì)影響父組件的屬性變化(props屬性類型是Object除外)。倘若使用vue1.0的.sync強(qiáng)制雙向,那么子組件的更改將會(huì)影響到父組件的狀態(tài),隨著業(yè)務(wù)的增多,很容易讓數(shù)據(jù)流變得難以理解,最終陷入痛苦的泥潭。因此,vue2.0已經(jīng)剔除.sync,且不允許在子組件中更改自身的props屬性。如果真的需要更改props,那一定是設(shè)計(jì)方案出了問題,請(qǐng)使用替代方案,如:在data選項(xiàng)或computed選項(xiàng)中再定義一個(gè)不同的變量進(jìn)行數(shù)據(jù)轉(zhuǎn)換。這是props down。

既然父組件可以通過props像子組件傳遞信息了,那子組件的數(shù)據(jù)變化如何通知到父組件呢?

$emit的出現(xiàn)便解決了這一問題,該方法用于 子組件向父組件發(fā)送事件消息,可帶上子組件的數(shù)據(jù)信息一起發(fā)送,父組件接收到消息后,做出自身相應(yīng)的變更。vue1.0 和vue2.0均支持$emit。這是events up。

如示例代碼1,父組件通過 age(props) 向子組件傳遞數(shù)據(jù)信息,子組件拿到后,通過$emit向父組件傳遞最新狀態(tài)。如果子組件涉及到可能會(huì)對(duì)age進(jìn)行更改,則重新定義一個(gè)變量age$進(jìn)行中轉(zhuǎn)。

【示例代碼1】

+ View Code

  

 

通信方式2(雙向綁定): .sync 或 v-model(建議在簡(jiǎn)單場(chǎng)景中使用)

在復(fù)雜邏輯組件中,一定不要使用.sync,很容易在N個(gè)組件中繞暈。如圖, A 是 BC 的父組件,AB和AC都雙向了一個(gè)共同的props屬性(如:model.sync)。B中的Model變化除了影響父組件A,A的變化進(jìn)而還會(huì)影響組件C,這時(shí)C就要爆炸了,這Model變化到底來自A,還是來自B。如此,Model的變化變得很難跟蹤,增大維護(hù)成本。如果B或C還watch model的話,啊呵,足以毀掉你一天的心情了。

 

 

父子組件直接雙向綁定是個(gè)隱式毒蟲,但對(duì)于某些基礎(chǔ)組件來說卻是只有益的蜜蜂,可以省掉不少麻煩。一些簡(jiǎn)單基礎(chǔ)的組件,或不需要關(guān)心數(shù)據(jù)流的地方 使用.sync 或 v-model就會(huì)是代碼顯得簡(jiǎn)潔,且一目了然。

示例代碼2 和 示例代碼3 效果圖: 

vue1.0修飾符.sync可以強(qiáng)制props屬性雙向綁定,如示例代碼2,checked為雙向綁定,可以輕松完成radio單選組件。

vue2.0中對(duì)prop屬性進(jìn)行直接賦值更改會(huì)拋錯(cuò),但如果prop屬性類型為object時(shí),僅僅添加或更改props屬性內(nèi)部的屬性不會(huì)拋錯(cuò)。由于此特性,vue2.0不支持.sync修飾符。

【示例代碼2】

+ View Code

  

 

vue2.0雖然已經(jīng)棄用.sync,但有語(yǔ)法糖v-model,其 實(shí)質(zhì) 就是 props down, events up,只是因?yàn)関-model隱藏了數(shù)據(jù)流,因此喚其為雙向綁定。 父組件向下使用props隱式屬性value將數(shù)據(jù)傳遞數(shù)據(jù)給子組件,子組件使用$emit('input')向上將數(shù)據(jù)返回給父組件。但正如上文所說,對(duì)于基礎(chǔ)組件或不關(guān)心數(shù)據(jù)流的組件使用雙向綁定是糟粕中的小蜂蜜,書寫簡(jiǎn)潔,清晰明了。

【示例代碼3】

 

+ View Code

  

 

     拆解語(yǔ)法糖v-model,如示例代碼4。已熟知的朋友可以略過。

     代碼第4行 <child :value="info" @input="dataChange"> </child>更為 <child v-model="info"></child> 效果一樣。

【示例代碼4】

+ View Code

  

 

 

通信方式3: $broadcast 和 $dispatch(不建議使用)

     只有vue1.0中才有這兩種方法。

  $dispatch首先會(huì)觸發(fā)自身實(shí)例,冒泡向上,直到某個(gè)父組件收到$dispatch消息。如果子組件內(nèi)部使用了$dispatch,那么該組件的 父組件鏈在寫監(jiān)聽事件時(shí)都必須格外小心,必須得有父組件截獲該消息,否則會(huì)一直冒泡。這是一項(xiàng)非常危險(xiǎn)的行為,因?yàn)?,父組件鏈中的組件 很難關(guān)注到所有子組件的dispatch消息,隨著$dispatch在組件中增多,頂層組件或中間組件想知道消息來自哪個(gè)子組件變得異常艱辛,事件流跟蹤困難,痛苦深淵由此開啟。

      $broadcast會(huì)向每一個(gè)子樹路徑發(fā)送消息,一條路徑某個(gè)組件接收消息,則該路徑停止向下發(fā)送消息,其它路徑規(guī)則一樣。同理$dispatch,隨著通信的增加,消息的增多,子組件也將很難跟蹤監(jiān)聽的消息到底來自哪個(gè)父組件。不注意的話,最后上演一場(chǎng)的 尋親記,想來也是持久精彩的。

      $dispatch 和 $broadcast 都已在vue2.0中被棄用,如果實(shí)在想堅(jiān)持使用,也可通過$emit進(jìn)行模擬,通過apply或call改變this,遞歸便利。

 

非父子組件間的通信

1. 狀態(tài)管理方案 vuex(建議使用)

適合復(fù)雜數(shù)據(jù)流管理。詳細(xì)使用方法見如下站點(diǎn),

https://github.com/vuejs/vuex

 

2. 中央數(shù)據(jù)總線(建議在簡(jiǎn)單的場(chǎng)景中使用)

      創(chuàng)建一個(gè)單獨(dú)的空Vue實(shí)例(Events = new Vue()),作為事件收發(fā)器,在該實(shí)例上進(jìn)行$emit, $on, $off等操作。適用場(chǎng)景:a. 使用Events.$on的組件不關(guān)心事件具體來源; b. 事件處理程序 執(zhí)行與否 或 重復(fù)執(zhí)行 都沒有副作用(如刷新、查詢等操作)。如示例代碼5,

      【示例代碼5】

+ View Code

  

      

      為什么說只適用簡(jiǎn)單場(chǎng)景呢? vue組件化的開發(fā)模式意味著一個(gè)組件很可能被多次實(shí)例化。請(qǐng)看下文分析,

      假設(shè) A組件使用Events.$emit('event'), 在同一個(gè)界面被實(shí)例化了兩次,現(xiàn)在的需求是,組件A實(shí)例1觸發(fā)消息'event'時(shí),組件B根據(jù)消息'event'相應(yīng)更新,組件A實(shí)例2觸發(fā)消息'event',組件B不能根據(jù)消息'event'進(jìn)行相應(yīng)的更新。這時(shí),因?yàn)榻M件B使用的是Events.$on('event')就搞不清是由A組件實(shí)例1觸發(fā)的消息'event', 還是A組件實(shí)例2觸發(fā)的。

      因此,使用該方法時(shí),最好保證組件在同一界面只會(huì)被渲染一次,或這不需要關(guān)心Events.$emit由哪個(gè)實(shí)例觸發(fā)。

 

 

3. 利用對(duì)象的值傳遞特性

適用場(chǎng)景:列表中,需要更改某條數(shù)據(jù)的某項(xiàng)信息。當(dāng)一個(gè)變量向另一個(gè)變量復(fù)制引用類型的值時(shí),復(fù)制的值實(shí)際上是一個(gè)指針,指向存儲(chǔ)在堆中的同一個(gè)對(duì)象。因此,改變其中一個(gè)變量就會(huì)影響另一個(gè)變量。  如,在一個(gè)表格列表中,如何在 N行X列 更改 N行Y列 的數(shù)據(jù)?

 

     【示例代碼6】

+ View Code

  

 

       

4. Vue-rx

    https://github.com/vuejs/vue-rx

  https://github.com/Reactive-Extensions/RxJS

 

簡(jiǎn)而言之,無論是vue1.0,還是vue2.0,為保證清晰的數(shù)據(jù)流 和 事件流,父子組件通信遵循“props down, events up”的原則。非父子組件根據(jù)不同場(chǎng)景選擇不同的方案,大部分情況依然建議使用vuex狀態(tài)管理方案。特別復(fù)雜的場(chǎng)景,建議使用vue-rx。

只有足夠努力,才能看起來毫不費(fèi)力!

http://www.cnblogs.com/codelovers/p/7048152.html