單元件多UI形態的終極解決方案(React)

bestVayne發表於2024-07-25

導語:前端開發者必然會遇到單個元件有多種UI的情況,UI種類越多,重複工作量越大,本文基於React提供一種解決思路。

1. 元件示例

拿一個商品元件舉例,總共十幾種UI形式,這裡列舉三種

商品標題

最大行數

是否展示庫存標籤

是否展示商品推薦詞

右下角功能

2

加購


2

加購


1

增加數量

2. 常規解法

遇到這種問題,常規的解法是封裝獨立小元件,例如

  1. 商品圖片元件
  2. 商品標題元件
  3. 商品標籤元件
  4. 商品xxx元件...

完整元件的程式碼結構大概是

<div className="goods-item">
  <GoodsImage image="xxx" />

  <GoodsTitle title="xxx" />

  <GoodsTag tagList={[]} />

  {type === 'cart' && <GoodsCart />}

  {type === 'num' && <GoodsNum />}
</div>

但這個方案存在一個弊端,當元件樣式比較少的時候一片祥和,隨著元件樣式不斷增多,問題會逐漸暴露,主要體現在:

  1. 通用邏輯每個頁面都要重新呼叫,比如埋點上報、點選跳轉商詳,導致重複程式碼增多。
  2. 如果迭代一個小元件,那麼所有使用的地方都要手動更新入參,導致維護成本大。
  3. 骨架屏的粒度控制比較麻煩,每個元件都要給小元件們傳入loading引數
  4. 程式碼複雜度越高,後期維護引起現網bug的機率越大。

3. 尋求出路

剖析它們的異同點,可以發現每個元件的資料結構和業務邏輯幾乎是一模一樣的,只有UI表現不一樣,而它們耦合得比較深,根據高內聚低耦合原則,可以將它們的相同點(資料結構和業務邏輯)內聚起來,而差異點解耦到各頁面中。

但如何做呢?React提供一種renderProps的語法,可以在一個根元件中將業務邏輯處理好,再吐出小元件供商品元件例項使用,根元件不關心UI,而元件例項只關心UI。

更生動形象的描述:

  • 樂高工廠接收塑膠原材料 -> 沖模加工成不同形狀 -> 生產出一堆標準化零件 -> 使用者自由組裝成不同的造型
  • 根元件接收商品資料 -> 處理所有業務邏輯 -> 生產出一堆標準化小元件 -> 開發者自由組裝UI

這樣不僅擁有常規方案的所有特性,而且能完美解決上述那些問題。

4. 程式碼重構

建立商品根元件

首先在根元件裡處理了曝光埋點、點選跳轉等通用邏輯;

其次封裝了很多小元件,每個useCallback都是一個獨立的可開箱即用的小元件,每個小元件都支援傳入style和className來定製樣式,然後將小元件吐出去給外部使用。

小元件示例

拿最簡單的商品標題元件舉例,它支援兩個額外引數

  1. maxLine:文字最大行數,超出則用省略號溢位隱藏
  2. isShowTag:是否展示文字前面的標籤

通用的商品標題渲染由元件內部處理,其他透過小元件的擴充套件引數支援。

根元件渲染了什麼

一般元件的children是實體dom元素,但我們利用React的renderProps特性,children定義成一個函式,外部在使用根元件時,透過傳入一個函式引用來實現自由度極高的自定義渲染。

使用根元件

可以很明顯的看到,外部在使用根元件進行渲染自定義商品元件時,沒有任何業務邏輯程式碼,它的職責非常單一且明確:只需關心UI表現。整塊程式碼看起來非常清爽。

4. 最終效果

這是其中一種UI改造前後程式碼量的對比:

感受完視覺衝擊,再來看看彙總資料:

  1. 改造定製化元件14個,程式碼量減少了900+行,佔元件總程式碼量的60%。
  2. 後期維護成本減少80%
  3. 改造後半年內相關現網bug由2降為0

可以看出改造效果非常顯著。

相關文章