Regular進階: 跨組件通信

本文由作者鄭海波授權網易云社區(qū)發(fā)布。


背景

在組件化不斷深入的大環(huán)境下,無論使用哪種 MDV 框架都最終會遇到一個頭疼的問題,就是「跨組件通信」。

下圖是個簡單的例子

這里包含「事件通信」和「數據通信」兩個維度。

事件傳遞

為了將事件?click?從?<LeafNode />?傳遞到最外層組件,需要依次通過?<SubNode />?和?<Sub />?等可能本不關心這個事件的組件(即使例子里已經使用了proxy的簡化語法)

數據傳遞

為了從?<Top />?傳遞?title?這個 prop 到?<LeafNode />?, 需要層層跨越?<Sub />、<SubNode />?這些本不需要關心?title屬性 的組件。

以上處理方式除了帶來性能上的損耗之外,更麻煩的就是造成了可維護性的急速下降。

顯而易見的事件通信解決方案

最直接的做法就是引入一個「中介者」,簡而言之就是一個全局的「跳板」,下例就是一個事件中介者

mediator.js

const?Regular?=?require('regularjs');const?emitter?=?new?Regular;//每個Regular組件都是一個事件發(fā)射器module.exports?=?{
????broadcast:?emiter.$emit.bind(emiter),
????subscribe:?emiter.$on.bind(emiter)
}

Top.js

const?{?broadcast,?subscribe?}?=?require('./mediator')const?Regular?=?require('regularjs');const?Top?=?Regular.extend({

????name:?'Top',

????init(){
????????subscribe('check',?ev?=>{????????????//?通過emitter廣播事件
????????})
????}
})

LeafNode.js

const?{?broadcast,?subscribe?}?=?require('path/to/mediator')const?Regular?=?require('regularjs');const?LeafNode?=?Regular.extend({

????template:?`<div?on-click={?this.onClick()?}?></div>`,

????name:?'LeafNode',

????onClick(){
????????broadcast(?'check',?{?type:?'leafnode'?}?)
????}
})

mediator?作為一個全局單例直接被?LeafNode?和?Top?引用,通過它實現(xiàn)了直接通信.

更麻煩的兄弟節(jié)點之間的通信當然也可以這樣來解決。

顯而易見的解決方案引出的另一個顯而易見的問題

上述中介者的引入的最大問題就是,所有相關組件都在?定義時?引入了對emitter的?全局耦合, 這個將導致組件無法在多工程間被復用。

一種合理的解決方案就是將對emitter的耦合, 延遲到實例化階段。

在Regular之前的版本里,很多朋友會通過this.$parentthis.$outer等可控性很差的方式來實現(xiàn),在v0.6有了一種更好的方式。

modifyBodyComponent?新生命周期

在 Regular 的?v0.6?引入了一個新的生命周期叫?modifyBodyComponent?,它用來劫持到組件包裹的所有內部組件的初始化周期。

我們用一個簡單例子來實現(xiàn)下emitter的動態(tài)注入

Broadcastor.js

const?Regular?=?require('regularjs');const?Broadcastor?=?Regular.extend({

????name:?'Broadcastor',

????config(?data?){????????const?emitter?=?data.emitter;????????this._broadcast?=?emitter.$emit.bind(emitter),????????this._subscribe?=??emitter.$on.bind(emitter)


????},

????modifyBodyComponent(?component,?next?){

????????component.$broadcast?=?this._broadcast;
????????component.$subscribe?=?this._subscribe;

????????next(component)?//?交給外層的包裝器
????}
})

Top.js

//?const?{?broadcast,?subscribe?}?=?require('./mediator')const?Regular?=?require('regularjs');const?Top?=?Regular.extend({

????name:?'Top',

????template:?'略...',

????init(){????????this.$subscribe('check',?ev?=>{????????????//?通過emitter廣播事件
????????})
????}
})

LeafNode.js

//?const?{?broadcast,?subscribe?}?=?require('path/to/mediator')const?Regular?=?require('regularjs');const?LeafNode?=?Regular.extend({

????template:?`<div?on-click={?this.onClick()?}?></div>`,

????name:?'LeafNode',

????onClick(){
????????this.$broadcast(?'check',?{?type:?'leafnode'?}?)
????}
})

main.js?(入口)

new?Regular({
????template:`
????????<Broadcastor?emitter={emitter}>????????????<!--?其中LeafNode?在Top內部?-->
????????????<Top?/>
????????</Broadcastor>
????`,
????data:?{
????????emitter:?new?Regular
????}
})

這樣所有的組件聲明都取消了對全局?emitter?的直接依賴,而是在入口(main.js) 動態(tài)傳入了一個emitter。

生命周期

需要注意的是modifyBodyComponent?會在 component本身compile之后運行, 但在init之前運行。以上面的例子為代表, 完整生命周期如下.

Broadcastor.config?->?Broadcastor.compile
????-?Top.config?->?Top.compile
????????-?LeafNode.config?->?LeafNode.compile
????????????-?Broadcastor.modifyBodyComponent(LeafNode)
????????-?LeafNode.init
????????-?Broadcastor.modifyBodyComponent(Top)
????-?Top.init
-?Broadcastor.init

下一篇,應該會以redux(rgl-redux)為例,介紹一種基于modifyBodyComponent來解決跨組件的數據通信的方式


免費領取驗證碼、內容安全、短信發(fā)送、直播點播體驗包及云服務器等套餐

更多網易技術、產品、運營經驗分享請訪問網易云社區(qū)


相關文章:
【推薦】?數據庫路由中間件MyCat - 源代碼篇(10)

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 最近再看阮一峰的一篇博客提到了一本書《Software Architecture Patterns》(PDF),寫...
    卓_然閱讀 8,270評論 0 22
  • 任何一個好的東西(語言、框架等)最終還取決于用的人 語言和框架本身并不能保證用戶的代碼清晰、解耦等, 當然它只是盡...
    約書亞Luis閱讀 887評論 0 1
  • 采購與供應商的關系,阿哥看來,就是亦敵亦友,又愛又恨。雙方之間,你來我往,為了利益最大化,既互相支持配合,也互相提...
    煙花阿哥閱讀 608評論 0 0
  • 坐在站牌的椅子上等公交,遲遲不來,馬路兩邊的廣告拍上全是優(yōu)衣庫的廣告。說實話,我也不知道這些品牌代言人,這些麻豆是...
    別人家的小強強閱讀 8,378評論 0 1
  • 這是續(xù)“培育別人的丈夫”(養(yǎng)育男孩)一課后又一深刻的反省。 討好型人格在我身上演練了多年,早已深入骨髓里了吧。遇到...
    Crystal婉韻閱讀 455評論 0 0

友情鏈接更多精彩內容