基于數(shù)據(jù)源驅(qū)動的跨組件通信最佳實踐(低碼篇)
hello, 大家好, 我是徐小夕, 之前一直在研究可視化零代碼相關(guān)產(chǎn)品的技術(shù)落地, 也分享了很多可視化低代碼的 技術(shù)實踐, 今天和大家繼續(xù)分享一下低代碼平臺中組件通信的一些技術(shù)方案和實現(xiàn).
背景
聊到低代碼或零代碼大家也許并不陌生, 國內(nèi)外有很多優(yōu)秀的低代碼或零代碼產(chǎn)品, 可以幫助我們更低成本的搭建頁面或者應(yīng)用. 從完整的業(yè)務(wù)搭建流程上看, 低代碼的頁面搭建能力需要具備如下3點(diǎn):
圖片
接下來我們重點(diǎn)介紹 跨組件通信能力.
為什么要實現(xiàn)跨組件通信
傳統(tǒng)的可視化搭建平臺更多的能力在于設(shè)計層, 我們使用它可以很好地搭建出靜態(tài)頁面, 比如易企秀, 早期的Dooring V1.0版本, 覆蓋的更多是宣傳頁, 電子相冊, 簡單的信息收集頁等:
圖片
image.png
為了讓可視化搭建平臺更多的滲透到業(yè)務(wù)層, 一定離不開以下兩點(diǎn):
- 復(fù)雜的交互邏輯
- 與數(shù)據(jù)接口的打通
復(fù)雜的交互能力 意味著我們搭建的每個組件都不是孤立的個體, 而是可以相互影響聯(lián)動的, 更多的還原真實開發(fā)的體驗(比如 vue 開發(fā)中通過 vuex 來實現(xiàn)組件間數(shù)據(jù)互通與交互, react 中的redux 或者 mobx 等實現(xiàn)跨組件的數(shù)據(jù)傳遞和互通).
圖片
和數(shù)據(jù)接口的打通 意味著我們要在組件搭建層讓用戶配置自定義的api接口和數(shù)據(jù)自定義的能力, 那么基于這樣的背景, 我們就可以設(shè)計標(biāo)準(zhǔn)的 數(shù)據(jù)源 來解決. 有關(guān)數(shù)據(jù)源的一些實現(xiàn)方案我也在之前的文章中分享過, 感興趣的可以參考一下:
- (低代碼)可視化搭建平臺數(shù)據(jù)源設(shè)計剖析
所以目前主流低代碼或者側(cè)重業(yè)務(wù)層面的零代碼平臺一定會滿足以上兩個痛點(diǎn), 這樣才能讓平臺更大程度的覆蓋業(yè)務(wù)場景, 實現(xiàn)降本增效的目標(biāo).
接下來我會分享一下如何基于數(shù)據(jù)源, 來實現(xiàn)跨組件通信.
效果演示
我們以常用的搜索功能來演示跨組件通信.
首先我們在搭建平臺拖拽1個搜索組件和一個商品組件:
圖片
2023-12-14 13.15.18.gif
然后將商品組件和搜索組件關(guān)聯(lián), 最后保存頁面訪問:
圖片
以上演示可以看到, 搜索組件可以將商品組件的內(nèi)容搜索出來, 進(jìn)而實現(xiàn)了組件聯(lián)動.
實現(xiàn)方案
圖片
我之前也分享了幾種常用的組件通信方案, 如下:
- props/$emit
- 子組件向父組件傳值
- eventBus($emit/$on)
- vuex / redux
- $attrs/$listeners
- provide/inject
具體的實現(xiàn)方式我在 低代碼平臺組件間通信方案復(fù)盤 有詳細(xì)的介紹, 這里和大家分享一下我最近設(shè)計的一種組件間通信的方案 —— 自定義事件通信.
沒錯, 我們用的就是 CustomEvent.
事件本質(zhì)上是一種通信方式,一種消息機(jī)制,我們在遇到多對象多模塊場景時,使用事件進(jìn)行通信是一種非常有效的方式。在多模塊化開發(fā)時,可以使用自定義事件進(jìn)行模塊間通信。
我們使用自定義事件也很簡單, 就像我上面畫的圖一樣, 我們只需要具備3個條件:
- 事件創(chuàng)建者
- 事件監(jiān)聽者
- 事件派發(fā)者
接下來我們用MDN的案例來說明如何使用它:
const form = document.querySelector("form");
const textarea = document.querySelector("textarea");
// 創(chuàng)建一個新事件,允許冒泡,并提供要傳遞給“detail”屬性的任何數(shù)據(jù)
const eventAwesome = new CustomEvent("awesome", {
bubbles: true,
detail: { text: () => textarea.value },
});
// 表單(form)元素監(jiān)聽自定義的“awesome”事件,然后在控制臺打印傳遞的 text() 方法的輸出
form.addEventListener("awesome", (e) => console.log(e.detail.text()));
// 當(dāng)用戶輸入時,表單中的文本區(qū)域會分派/觸發(fā)事件,并以自身為事件的起點(diǎn)
textarea.addEventListener("input", (e) => e.target.dispatchEvent(eventAwesome));
以上就實現(xiàn)了一下自定義事件的監(jiān)聽和派發(fā), 我們可以讓不同的元素監(jiān)聽同一個事件, 并進(jìn)行不同的邏輯處理.
同時它的兼容性也非常好, 主流瀏覽器都支持:
image.png
有了以上基礎(chǔ), 我們接下來來實現(xiàn)一下在低代碼中基于事件的組件通信模式.
基于數(shù)據(jù)源驅(qū)動的跨組件通信
上面介紹了跨組件通信, 但是我們?yōu)榱俗寴I(yè)務(wù)層能更好的接入低代碼或者零代碼, 我們需要設(shè)計統(tǒng)一的數(shù)據(jù)源規(guī)范.
對于數(shù)據(jù)源的設(shè)計, 根據(jù)實際的業(yè)務(wù)需求, 我們可以分為靜態(tài)數(shù)據(jù)源和動態(tài)數(shù)據(jù)源. 靜態(tài)數(shù)據(jù)源是用戶可以通過可視化的方式在低代碼平臺上創(chuàng)建的, 比如編輯數(shù)據(jù)表格等.
動態(tài)數(shù)據(jù)源是指用戶可以自定義的請求第三方的數(shù)據(jù)服務(wù), 組件消費(fèi)數(shù)據(jù)源完全是動態(tài)調(diào)用的, 類似于我們傳統(tǒng)開發(fā)時使用的ajax請求.
圖片
當(dāng)然為了保持普適性和接入的規(guī)范性, 我們需要提前約定數(shù)據(jù)源的字段和字段格式, 這樣不同企業(yè)的業(yè)務(wù)數(shù)據(jù)都可以通過適配器來被通用的低代碼組件消費(fèi). 這里分享一下 Dooring 的零代碼創(chuàng)建數(shù)據(jù)源的模式:
圖片
數(shù)據(jù)源其實就是用戶的一個通過可視化的方式來創(chuàng)建管理的數(shù)據(jù)庫, 我們可以靜態(tài)的錄入數(shù)據(jù), 也可以動態(tài)的通過接口獲取數(shù)據(jù):
圖片
圖片
然后我們在組件配置面板中就可以一鍵綁定數(shù)據(jù)源了:
圖片
接下來我們來實現(xiàn)組件通信的部分, 效果如下圖:
圖片
首先在搜索組件中創(chuàng)建事件并派發(fā):
const handleSearch = () => {
if(targetId) {
document.dispatchEvent(new CustomEvent(`search_${targetId}`, { detail: textRef.current.value }))
}
}
為了保持事件被監(jiān)聽的對象可控, 我們需要通過組件id來明確指定組件的監(jiān)聽目標(biāo), 所有事件名可以用目標(biāo)id + 業(yè)務(wù)詞來組成.
接下來我們可以在商品組件來設(shè)計統(tǒng)一的監(jiān)聽:
useEffect(() => {
const eventName = `search_${id}`;
function handleDataChange(event: any) {
// 將數(shù)據(jù)傳遞給業(yè)務(wù)函數(shù)
handleSearch(event.detail);
}
document.addEventListener(eventName, handleDataChange)
return () => document.removeEventListener(eventName, handleDataChange)
}, [])
這樣我們就能將 搜索組件的值通過 event.detail 方式傳遞給商品組件, 并在搜索按鈕中觸發(fā)事件的執(zhí)行, 從而影響商品組件的業(yè)務(wù)函數(shù)的執(zhí)行.
當(dāng)然這只是一個簡單的案例, 我們還可以利用這樣的機(jī)制設(shè)計更復(fù)雜的通信, 比如事件隊列, 讓一個組件依次執(zhí)行一系列的事件邏輯.
圖片