低代碼平臺組件間通信方案復盤(低代碼平臺搭建)
背景介紹
3年前我開發了一款零代碼搭建平臺 H5-Dooring, 主要目的是想用更低的成本, 更快的效率, 上線 web 頁面(其實是不想寫重復的代碼了,寫麻了). 好在陸陸續續折騰了3年, 目前已經可以滿足基本的頁面設計和搭建能力, 并能快速上線頁面.
之前也在社區分享了很多低代碼和零代碼的技術實現, 接下來繼續和大家聊聊低代碼平臺中組件與組件之間的通信方案設計.
可視化搭建平臺的基本能力
根據我自己設計可視化搭建平臺的經驗, 其需要具備最最基本的兩個能力:
- 靜態頁面設計能力(也就是可以用可視化平臺制作我們想要的頁面的能力)
- 組件交互能力(制作好靜態頁面之后, 頁面元素能具備一定的交互, 比如跳轉鏈接, 打開彈窗等)
以上的能力可以讓我們將頁面通過拖拽的方式搭建出來:
雖然這已經可以滿足很多展示型的需求, 但是仍然存在局限性, 比如可視化平臺的組件與組件之間, 沒辦法相互通信.
更靈活自主的可視化搭建平臺
這里給大家舉一個實際的場景, 比如我們要做一個轉盤H5頁面, 它由轉盤組件和按鈕組件組成, 當點擊按鈕時, 轉盤開始運動:
這種場景就需要轉盤組件和按鈕組件相互通信, 來實現交互功能. 所以在可視化搭建平臺中, 如果能實現組件間的通信, 那將覆蓋更多的業務場景, 從而為個人或者企業帶來更大的價值.
接下來我將和大家分享一下低代碼平臺中組件間通信的幾種方案, 共大家學習參考.
組件間通信的幾種實現方案
說到組件通信我們也許并不陌生, 比如在 vue 或者 React 框架中, 經常會涉及到父子組件通信以及組件與組件間的通信, 常用的方案也有很多, 比如:
- props/$emit
- 子組件向父組件傳值
- eventBus($emit/$on)
- vuex / redux
- $attrs/$listeners
- provide/inject
當然還有很多方式能幫我們實現傳統組件間的通信, 那我們在低代碼組件中, 也可以參考類似的方式來實現, 但是唯一的區別是需要設計一套規則, 來保證組件間通信可以通過用戶配置的方式來運轉.
接下來我們來分析幾種低代碼組件間的通信方案.
1.websocket
在設計組件通信方案前, 我們需全局維護一個公共的狀態, 拿 H5-Dooring可視化平臺 舉例, 我們用 redux 管理公共狀態, 組件間通信本質就是觸發公共狀態的更新:
為了保證低代碼組件庫足夠純凈, 比如不應該在組件里連接 redux, 所以我們需要把 redux 觸發器 dispatch 放在頁面的全局, 這里就可以用 websocket, 在組件里觸發 socket 指令, 在頁面全局來監聽, 并觸發 dispatch :
當然使用 socket 的方式仍然會讓低代碼組件庫負重前行(雖然能實現更自由的通信場景, 比如組件自更新, 生命周期回調, 控制業務鉤子等), 因為我們不得不為其搭建 socket 服務, 并且需要為其設計穩定的通信橋梁, 比如 socket 心跳連接等.
2.Iframe通信 postmessage
利用 iframe 的 postmessage 等 API 雖然也能實現組件間通信, 但是我們需要設計一套通信機制, 保證 iframe 能接受組件傳送的指令, 并對外暴露共享狀態:
我們從 Iframe 的通信模式可以發現它不僅可以作為中間橋梁起到通信作用, 有點類似于 eventBus的模式, 而且還可以實現頁面間的通信, 比如目前很多微前端架構的底層支持也有采用 iframe 來設計的. 但是對于更細粒度的低代碼組件來說, 有點小題大作了.
接下來給大家分享一下 iframe 通信的基本代碼實現:
// 父頁面和子頁面通信// A.html (父)<iframe src="http://h5.dooring.cn/h5_plus" frameborder="1" id="Bframe"></iframe>const msg = { name: "H5-Dooring" }window.onload = () => { // 自動調用必須放在onload中,通過事件調用則不用 // let frame = document.querySelector("#Bframe").contentWindow let frame = window.frames[0] frame.postMessage(msg, "http://h5.dooring.cn/preview")}// B.htmlwindow.addEventListener("message", (e) => { console.log(e.data) console.log(e.origin) console.log(e.source)})// 子頁面和父頁面通信// A.html (父)<iframe src="http://h5.dooring.cn/h5_plus" frameborder="1" id="Bframe"></iframe>window.addEventListener("message", (e) => { console.log(e.data) console.log(e.origin) console.log(e.source)})// B.htmlconst msg = { name: "Dooring H5"}window.top.postMessage(msg, "http://h5.dooring.cn/preview")
3.Event Emitters
Event Emitters 的方式我覺得是最適合低代碼組件間通信的方案, 類似于 js 里的事件監聽機制, 我們可以給 dom 綁定監聽, 并暴露事件給用戶來實現手動觸發機制. (雖然不一定是用戶手動觸發, 也有一種情況是邏輯觸發, 比如當頁面某個組件到達某一狀態的時候, 后自動觸發事件, 來改變其他組件的狀態)
Event Emitters 類似一種觀察者模式, 我們可以利用 javascript 的設計模式來實現它, 并在組件內部來監聽或者觸發, 一個簡單的實現如下:
interface Events { [key: string]: Function[];}export class EventEmitter { public events: Events; constructor(events?: Events) { this.events = events || {}; } public subscribe(name: string, cb: Function) { (this.events[name] || (this.events[name] = [])).push(cb); return { unsubscribe: () => this.events[name] && this.events[name].splice(this.events[name].indexOf(cb) >>> 0, 1) }; } public emit(name: string, ...args: any[]): void { (this.events[name] || []).forEach(fn => fn(...args)); }}
具體設計流程有點像我之前設計的 iframe 通信架構, 不過使用起來會更簡單:
低代碼組件事件隊列設計
以上只實現了組件的通信, 并沒有將通信和實際的應用場景結合起來, 比如低代碼用戶需要如何操作,才能實現組件通信. 這里我之前也設計了一套模型:
每個組件都有一套事件列表, 用戶可以給一個組件添加多個交互事件, 在第代碼內部通過循環遍歷來依次觸發事件隊列:
事件通信就可以用上面介紹的 Event Emitters來實現, 具體的低代碼模式可以參考我之前的項目:
- H5-Dooring可視化低代碼平臺
總結
后續我會繼續和大家分享一下 H5-Dooring 低代碼的更多實踐和思考, 如果大家對可視化低代碼感興趣也可以參考我的低代碼可視化專欄.
下一篇文章我會和大家分享一下低代碼印章組件的實現方案, 大家有更多好的建議也可以隨時和我反饋.
H5-dooring低代碼
H5-dooring低代碼
V6.Dooring可視化大屏搭建平臺
V6.Dooring可視化大屏搭建平臺