你不知道的前端組件庫

        關於組件庫設計的文章一搜能出來一大把,但大多數都是從UI角度或者視覺規範層面來說的,但隨着前端技術的發展和迭代,前端這個崗位早已不是過去定義的實現樣式那麼簡單了,這篇文章會站在一個技術同窗的角度來聊一下組件庫的設計除了樣式還有哪些能夠關注的。javascript

組件庫應用場景思考

        組件的本質其實在於代碼的複用和抽象,以此起到提高開發效率的目的, 能夠說一個組件的靈魂就在於對業務場景的解構,好比各類控件的抽象,事件的抽象,樣式的抽象等,並經過組合和配置的方式實現業務需求,某種程度上一個組件庫就像是一個工具箱,爲業務場景的開發提供各類零件,而要如何設計這些零件,就須要對應用場景有一個深刻的瞭解和思考。前端

        好比C端的組件庫,須要在UI,性能,瀏覽器兼容性上有更多的思考,追求更極致的交互體驗和視覺體驗,同時C端應用的應用場景常常會根據節日,活動的主題而切換, 在組件庫的設計上也要考慮到個性化的擴展空間。java

        而B端的組件庫,則更加註重易用性和可複用性,保證中臺或者B端工具類應用的高速迭代和高效使用。同時B端應用會涉及不少的數據展現,和增刪改查操做,這就須要組件庫在交互控件上有更細的職責劃分和更豐富的選擇。react

        除了應用的業務場景不一樣,還可能存在平臺場景的多元化問題,好比同一套組件庫是否能在H5和小程序中複用。這些都須要組件庫設計者在規劃之初就考慮進去。webpack

目前主流的組件庫分析

目前主流的組件庫能夠分爲兩大類:

        一類是基於幾大前端框架的生態來實現的,在設計上都已經造成了本身的風格和規範,也有本身的沉澱,好比基於Vue生態的element, 基於react的antD 等。他們的優勢是已經發展的很成熟了基本上能夠cover大多數的業務場景,缺點是組件庫在跨框架遷移上的成本較大。web

        除了這類基於前端框架維度設計的組件庫,還有一些組件庫則是針對跨平臺的需求設計的。一般底層會依賴一套跨平臺開發的框架 如京東的taro,美團的mpVue, 淘寶的Rax等,他們的核心思想也是 write one run anywhere, 這類組件庫在實現上, 主要利用框架提供的基礎實現儘量抹平各個平臺的差別,讓使用者能夠基於一套開發規範,實現多個平臺的業務。這類組件的優勢是,能夠減小開發者在跨平臺上的學習成本,缺點是組件庫的豐富度還有所欠缺。canvas

組件庫的規劃

        組件庫的設計過程其實也很相似一款產品的設計過程,會有前期的場景調研,競品分析, 需求整理,用戶體驗(這裏應該叫開發體驗),以及持續的試錯迭代。小程序

綜合上面的一些思考和分析,我會試着把組件庫規劃以下:瀏覽器

組件需求:前端框架

  • 組件膠水層 --> 實現組件和實際的業務之間的銜接

  • 組件代理層 --> 能夠基於代理實現組件內部的靈活調用和局部刷新

  • 組件交互層 --> 根據業務場景 抽象基於交互事件的功能,並經過裝飾器注入

  • 組件擴展層 --> 實現組件間的克隆,繼承,擴展

  • 組件庫cli --> 方便組件的迭代和工程化

  • 性能 --> 實現最小粒度的從新渲染

組件庫解決痛點

  • function component 外部不方便繼承擴展
  • 實現組件和調用方交互時的局部更新,提升性能
  • 經過膠水層和前端框架鏈接,下降框架遷移的成本
  • 封裝事件驅動的狀態管理,也能夠配合一個狀態組件作擴展

組件內部系統:

  • 樣式

  • 事件

  • 狀態

  • 繼承

組件庫features:

  • 局部刷新 和 跨層級調用
Modal.proxy.visible = true;
複製代碼
  • 擴展繼承

    //克隆
    const Modal2 = Modal.clone();
    複製代碼
    //擴展
    const Modal2 = genModal({
        methods: {
          cancel() {
            console.log('%c rewrite the cancel','color:#299865',this);
            this.visible = false;
          }
        }
     });
    
    複製代碼
    //批量擴展
    import {factoryAuto} from 'component'
    const {Button, Modal} = factoryAuto(pubConfig);
    複製代碼
    //繼承
    const Button2 = genButton(Button1.proxy, newFeature)
    複製代碼
  • 輕量的狀態組件

<Button 
         x-for={(item, key) in statusList} 
         type="+success" 
         onClick={_ => trySingle(item)} >
        wait{key}
     </Button>

複製代碼
function trySingle (item) {
        performance.watch()
        item.choosed = !item.choosed
        if (item.choosed) {
          return new Status('choosed', { backgroundColor: 'green' })
        } else {
          return new Status(null)
        }
  }

複製代碼
  • 裝飾器注入
@addTransition('visible')  
   class BaseMix extends Base {}
複製代碼
  • scope做用域組件(局部render)
<Button scope={item}  
    x-for={(item, key) in scopeList} 
    type="+success" 
    onClick={(scope) => {tryScope(scope, item)}} >
    wait{key}
</Button>

複製代碼
function tryScope(scope, item) {
    performance.watch();
    item.choosed = !item.choosed;
    scope.choosed = !scope.choosed;
  }

複製代碼
  • 事件裝飾器(loading, lock等)
@addLoading
    class EventCtxMix extends EventCtxBase {}
複製代碼
function Okfunc() {
        return new Promise((resolve, reject) => {
            //封裝了防重鎖和loading效果
            setTimeout(() => {
              resolve()
            }, 1600)
        })
    }
複製代碼

組件庫架構圖

組件庫將來展望

        前端技術的一個特色就是變化快,除了各大框架提供的組件能力, 這幾年web components 的概念也逐漸成爲熱點。除此以外隨着react hooks的橫空出世 function components時代也隨之而來,相比於class compontents 基於hooks的function compontents在設計上更加靈活但外部擴展性也相對較差,基於這層考慮我有一個大膽的構想是在框架上層封裝組件的邏輯層和樣式層的接口,經過膠水層和組件鏈接只借助組件完成視圖層的渲染,從而打破組件庫和框架的次元壁,組件庫的核心部分能夠遷移到其餘框架甚至web compontents,只須要從新coding膠水層就好了。固然這個構想距離最終落地還須要大量的實踐基礎。

友情連接

webpack構建流程及梳理
UI自動化測試框架Cypress初探
canvas在前端開發中的實踐
相關文章
相關標籤/搜索