Taro多端元件庫的設計與實現

語言: CN / TW / HK

highlight: a11y-dark

本篇文章基於業務中搭建多端元件庫的經驗撰寫

image.png

一、背景

1.1 背景

  • 團隊業務:C端商城,需要支援小程式、H5
  • 團隊技術棧:Taro+React多端 打怪過程如下: image.png step1: 部門剛成立的時候,業務跑的很快,從0-1建設多端商城,給我們搞技術的時間幾乎沒有,所以一上來,我們選用了taro-ui元件庫,使用下來我們發現,好用的元件庫很少,且問題很多,官方也停止更新了,最後一個版本在20年4月份

step2: 為了滿足業務,我們開始直接在業務中直接寫元件,暴露的問題自然更明顯:元件難複用、難擴充套件

step3: 所以在21年10月,當我們又新增了兩塊多端商城的業務時,可預見一個元件庫來幫助團隊提高開發效率是很有必要的,所以我們趁著做業務的同時自建元件庫,並與21年12月釋出了第一版(同事當時寫的文章)

step4: 時隔一個季度,我們在技術實現了一些突破,比如用 hook 代替 class,用 css變數 全量替換 less變數,新增ConfigProvider全域性配置元件,支援自定義樣式字首動態切換主題...(在第三部分元件庫設計與實現會詳細介紹)

1.2 業內Taro-React元件庫分析

在開始動手之前,我們搜尋了全網Taro-React的元件庫 ~~(缺少搭建元件庫的經驗只能多看別人的!!!)~~

image.png

二、元件庫介紹

Alt

定位:一套基於 Taro 框架開發的多端 React UI 元件庫

Tard 取名自 Taro React Design 簡寫,發音特的

先貼幾張元件庫效果圖 1. 元件庫官網 image.png

2.2 元件示例

image.png

2.3 元件分類

目前31個元件(都是我們業務中用到的)+ ConfigProvider全域性配置元件,分為6類,具體可見下圖 image.png

元件庫更多可見官網 url:https://tard-ui.selling.cn/introduce

三、元件庫設計與實現

image.png 作為一個元件庫,最基本需要包括三個部分 - 元件:npm包,業務真正使用的 - demo:元件庫h5、小程式demo;元件的使用效果 - 文件:元件庫官網和文件,告訴別人怎麼用

3.1 元件庫規範

開始動手寫程式碼之前,一定要制定一套規範,除非一個人寫元件,不然多個人最後的元件庫寫出來可能五花八門;

開發過程中我們也經常因為意見不合,爭吵過很多次,討論後都達成一致,這是一個不容易的過程;所以儘可能的提前制定規範,不然中途來改成本很大,畢竟誰也不想反覆修改程式碼

3.1.1 程式碼管理方式

1、monorepo

packages包括以下三塊 - ui:元件庫 - sites:元件庫官網和文件 - demo:包包括h5、小程式demo image.png 2、ui(元件庫)程式碼組織

我們研究了其他各個元件庫怎麼組織元件的程式碼,一個元件包括的檔案有元件的型別ts檔案樣式檔案demo使用文件;最終決定將一個元件涉及的程式碼集中在一個資料夾下,一定程度上避免重複切換資料夾,提高開發效率

image.png

3.1.2 元件設計規範

1、元件編碼

統一使用Hook+TypeScript

2、元件命名

大駝峰,多元件以.的形式命名,對外一個元件只暴露一個元件,如下 - 按鈕:Button - 下拉選單:DropdownMenu,DropdownMenu.Item - 對話方塊:Modal,Modal.Header,Modal.Content,Modal.Action

3、元件API - 每個元件最外層需要包一個CompContainer元件,來實現元件有一些通用的引數,如下 - className - style - 不同元件相同型別引數命名統一,比如 - 元素的文字內容:text - 是否展示遮照:overlay - ... 4、元件樣式 less+BEM+css變數 - 使用統一字首(預設tard),效果如下 - css:@--css-prefix: tard - js:cssPrefix(){return 'tard'} - 遵循BEM規範 - 樣式變數:分為以下兩種,元件變數依賴基礎變數,提供更友好的方式修改元件樣式,而非傳統的強制改樣式 - 公共基礎變數 - 元件變數:在每個元件資料夾的 var.less 檔案中 - 多端相容 - :root, page{...}

css變數h5掛在 :root 下可生效,小程式需掛在 page 下生效

image.png

3.2 自定義樣式字首

可以呼叫 ConfigProvider.config 配置方法設定元件的class字首名,預設是 tard,比如下面我們設定為 custom js // 入口js檔案 import { ConfigProvider } from 'tard' ConfigProvider.config({ cssPrefix: 'custom' }); 同時需要配置樣式檔案字首名,在入口樣式檔案按如下配置 less @--css-prefix: 'custom'

注意:ConfigProvider.config 配置的 cssPrefix 一定要與樣式配置的 @--css-prefix 一致,否則class名與style不對應,樣式失效

3.3 定製主題

主題定製作為元件庫最基本的功能必不可少,分為兩類 - 編譯時定製主題;這類最常見,基本業內元件庫都支援,一般通過自定義樣式變數覆蓋,或者結合打包工具比如webpack配置loader處理 - 執行時定製主題:一般是前端提供集中模式供使用者切換或者通過介面拿主題資料;前者業內常用的方案有前端內建幾套樣式變數去切換,而後者一般是裝修場景下的需求,我們業務涉及到這塊,因此我們提供了 ConfigProvider實現執行時切換,具體可見3.3.2

3.3.1 自定義CSS變數

Button 元件為例,官網文件可以檢視元件的樣式,可以看到 Button 類名上存在以下變數 less :root, page { --button-height: 76px; --button-default-v-padding: 40px; --button-min-width: 192px; --button-min-width-mini: 120px; --button-height-mini: 32px; --button-mini-text-size: 24px; --button-mini-v-padding: 6px; --button-min-width-small: 144px; --button-height-small: 56px; --button-small-text-size: var(--font-size-base); --button-small-v-padding: 24px; --button-min-large-width: 360px; --button-large-height: 96px; --button-large-text-size: var(--font-size-lg); --button-large-v-padding: 48px; --button-radius: var(--border-radius-md); } (1) CSS 覆蓋

你可以直接在程式碼中覆蓋這些 CSS 變數,Button 元件的樣式會隨之發生改變: less :root, page { --button-radius: 10px; --color-primary: 'green' } 這些變數的預設值被定義在 root 節點上,HTML 文件的任何節點都可以訪問到這些變數

這也是編譯時定製主題常用的解決方案

(2)通過 ConfigProvider 覆蓋

ConfigProvider 元件提供了覆蓋 CSS 變數的能力,你需要在根節點包裹一個 ConfigProvider 元件,並通過 style 屬性來配置一些主題變數

這使得可以在執行時動態的更改主題 js // 比如 button-radius 會轉換成 `--button-radius` <ConfigProvider style={{ 'button-radius': '0px', 'color-primary': 'green' }}> <Button className="button-box__item" type="primary">主要按鈕</Button> </ConfigProvider>

注意:ConfigProvider 僅影響它的子元件的樣式,不影響全域性 root 節點

3.3.2 執行時動態主題

在官網ConfigProvider 全域性配置下可以體驗線上動態切換主題 image.png 呼叫 ConfigProvider.config 配置方法設定主題色 js ConfigProvider.config({ theme: { 'color-primary': 'purple', "button-radius": '20px' } });

3.4 文件實現

image.png

3.5 打包實現

image.png

四、元件庫建設經驗

這一部分主要寫元件庫建設經驗,如果說上面是技術上的經驗,這部分是人跟事上的經驗,畢竟一個元件庫要做出來並能持續擴充套件還真不容易,甚至說比技術更難

4.1 誕生之路

其實剛開始做這個元件庫過程很艱難,沒有專業的UI支援;一方面UI資源緊張,另一方面團隊沒有相應的KPI是建設元件庫,元件庫僅僅是用來滿足業務的

我們負責封裝元件給其他同事用,寫業務的同事元件催的急,我們是利用業務的設計稿中去實現的元件,比如業務設計稿中下拉選單張這樣,那我們就按照業務設計稿實現,沒有辦法...

但是元件庫脫離了UI很難幫助業務,畢竟設計稿是UI給到前端的;難道就滿足這一個業務,後面還有類似的場景呢?所以導致前期元件庫處於一個不規範的局面

轉機出現在,在寫業務的過程中我們發現同一個業務的不同頁面設計搞不統一,比如按鈕圓角、篩選列表的篩選條件...因為我們將其封裝成一個元件,那麼相應的樣式肯定是相對固定的,因為一個系統的設計風格肯定是需要保持一致的,除了可以通過樣式變數更改,所以我們與UI同學討論,在討論的過程中,我們透露了元件庫的思想,視覺規範一致的必要性,可以提高前端開發效率、UI設計效率

然後有一位UI同事比較感興趣,於是我們針對聊了很多,私下花時間專門支援我們,官網也是UI同事幫忙設計的

4.2 尋找突破

中途我們嘗試跟主管溝通過元件庫沒有UI,能不能協調下我們做的元件庫需要UI支援,但是目前沒有UI能支援,且重點是滿足業務,所以元件庫並沒有投入資源

興趣使然或者說出於對技術的學習心態吧,我們3個前端+一個UI一心想把元件庫給做好,於是我們開始借鑑業內元件庫的技術實現,設計語言與前端程式碼如何結合

就好比設計給出了一個按鈕的樣式,她得知道這個按鈕元素應該包括哪些內容(高寬、高度、字型、內間距等),這些就是設計規範,那這些規範對應的值就是設計語言。再更深層次的設計這些內容背後的邏輯是什麼,規範的原理什麼的就可以抽象出設計原則

這裡的設計語言對應到前端也就是樣式變數

UI同事開始給每個元件出稿,每個元件不同形態都有設計;前端開始制定規範,實現元件的同時思考API、樣式變數定義的是否規範,元件的demo、文件都補充起來,並進行code review

制定了每週開會機制,一個元件從設計稿設計、前端開發、code review、UI走查到達到要求的路徑,如下 image.png

開始設計元件庫的官網,想把元件庫做大最強,真正幫助大部門多端的業務(夢想還是要有的)

大家熱火朝天,雖然頻頻爭吵,好不快樂!

我們深知元件庫的視覺規範需要大部門都認同的前提下,才能發揮作用,於是當我們元件庫做的有模有樣了之後,我們將我們的成果彙報給了主管,希望主管能協調去大部門的UI與前端,統一規範

這些彙報(或者說元件庫的未來規劃)也算是我們在做元件庫的時候,對元件庫(或者說更高一層C端視覺規範統一)價值整體的一個認知吧,這些也是我們參考了很多資料總結的,大概如下

可能寫的都是比較理想的,大家可以理性參考...這當初的確是我們的目標,不過現在實在沒時間 image.png image.png 未來規劃 image.png image.png image.png

4.3 歧途

本來技術能真正幫助業務是一件好事,理想是美好的,現實的艱難的,Q1後期吧,可能資源協調確實困難,加上組織架構頻頻調整,視覺統一共建的事情遲遲難以落地,所以說目前元件庫確實滿足業務就是最好的選擇

寫在最後

寫這篇文章以及元件庫開源的原因是希望我們踩過的坑能給大家一些經驗,以及如果你對開源感興趣可以加入我們一起打造元件庫,或者需要taro-react多端元件庫的話可以嘗試使用tard

GitHub地址: https://github.com/jd-antelope/tard