如果把程式設計比作一門武學,除了掌握紮實的基本功外。想要進階為大宗師,我們還得內外兼修,掌握像vue,react等高階招式。更重要的是需要精進物件導向的高階內功心法。
什麼是模組化
在前端發展歷程中,起初並沒有模組化的概念,從原生js開發到jQuery一把梭,一個html中穿插著各式各樣的js檔案,相互之前不好隔離,變數與方法都是提升到全域性。隨著專案複雜度的提升,變得不利於維護管理。並且沒辦法很好的滿足“高內聚,低耦合” 的思想。逐漸的,模組化開發在社羣裡面流行了起來。
前端模組化可以將一個大型的前端專案拆分成多個小模組,方便管理和維護。常見的前端模組化規範有 CommonJS、AMD、CMD 和 ES6 Module。
這些模組化方案都各具特色,這裏優先建議使用ES6 Module
什麼是元件化
其實web從一開始變有了元件化的思想,只是直到react,vue等流行起來之後,元件化的思想纔開始深入人心,伴隨著我們的日常開發。
在元件化的思想裡面,我們認為一個網頁的呈現可以由若干個UI元件組成,一個元件只是網頁組成部分的一個單位而已。而元件化又十分靈活,我們可以元件巢狀,組合,打散等等,將各類複雜應用合理的拆分成一個個便於維護的元件單位。然後形成一棵枝繁葉茂的元件樹
原生元件化(Shadow DOM)
html中有各式各樣的標籤,這些標籤就是一個個的元件。例如:video,input,button...等等,都html內建好的web component。
除此之外,我們也可以透過 shadow DOM
的方式去自定義實現一個原生的web元件。
框架元件化(react,vue,angular,svelte...)
這些主流的前端框架更加豐富了元件的定義,生命週期,元件通訊,資訊隔離等等功能,利用現在主流的前端框架,我們可以輕鬆的實現元件化開發,極大提高了開發效率與質量。
元件化開發的設計思路
當我們對一個專案或者網頁進行元件化設計的時候,應該權衡利弊,找到一個合理的平衡點。因為過渡的拆分元件會使得程式碼過於分散,複雜度高。如果元件抽象程度不夠,程式碼又過於冗餘,複用性不高。如何透過合理的設計元件,來對程式碼進行解耦與分類,是一個值得思考的問題。
在各類場景下應該如何封裝元件?
對於何時應該封裝一個元件,每個人的見解都不一樣。有人認為多處地方使用了相同的邏輯,就應該抽離一個元件,有人認為元件拆分之後程式碼變多了,元件之前通訊變複雜了,還不如不封裝元件。那麼在面對複雜多變的需求業務場景下,我們應該如何去合理拆分元件呢?
一、 分析網頁的UI組成
當我們在UI設計師哪裏拿到一張精美的設計稿的時候,我們首先是需要看著設計稿開始分析網頁的組成部分是什麼?例如一個後臺管理系統,最經典的就是聖盃佈局,整個網頁可以分為“頭部導航欄”,“左側選單”,“右側內容”,“底部描述”。基於基本佈局,我們至少便需要封裝四個基本元件,再根據元件複雜度進一步拆分
二、 元件顆粒度定義
● 原子級元件:最小單位的元件,這類元件通常只包含一個單一功能,不參雜多餘的業務程式碼。例如網頁中的按鈕,圖示,輸入框,下拉框等。原子級的元件應該具備最大通用性與複用性。市面上大多數UI元件庫提供了許多原子級元件,極大提高了開發效率。
● 分子級元件:由多個不同的原子級元件組成,通常實現了一些基礎常見的功能模組。例如:級聯選擇器,穿梭框,標籤頁等。
● 複合型元件:由多個不同的原子級和分子級元件組成,通常實現了一些較為複雜的業務功能。例如:表格,表單,日曆,tree樹等。
● 頁面級元件:集大成者,由多個不同的原子,分子,複合元件組成,通常實現了一些具有獨立業務需求的功能模組。例如:購物車列表,收貨地址設定,導航選單等。
三、 什麼情況下應該抽離元件?
講了這麼多,那麼在面對日益複雜的業務需求時。怎樣合理的抽象元件,達到一個合理的平衡點呢?在什麼情況下,我們需要抽離元件出來呢?
● 頁面UI層次分明,複雜度高
○ 當頁面UI層次分明且複雜度高的時候,我們第一時間應該是考慮“拆”,根據頁面特性,ui展示,業務需求不同維度去拆成一個個元件
● 多出地方使用,出場率高
○ 當一個ui元件會以相同的形式出現在不同地方,只需要透過引數控制即可滿足不同場景時。便可以考慮將這些邏輯封裝成一個元件多處使用了
● 具備完整的功能閉環
○ 某些業務場景功能比較純粹,功能單一且能完整閉環,例如某個純展示的卡片資訊面板,步驟條顯示,一些特定業務邏輯處理的包裝元件等。這個時候變可以考慮將其封裝成一個元件。
● 業務極其複雜且耦合度高
○ 在面對業務複雜且耦合度高的需求開發時,就可以利用元件拆分來對程式碼進行解耦以達到邏輯分解,關注點分離,提高程式碼質量的目的
● 無需關注內部實現,只關心結果呈現
○ 日常開發中經常會遇到一些“黑匣子”開發,在此類場景上我們往往不需要關注元件內部實現,只需要該元件能在網頁上正常執行預期結果即可。例如:一個圓形的餅狀統計圖,一個播放器的二次包裝,一個canvas畫板容器等
如何設計一個優秀的元件
說一千道一萬,我們應該如何才能設計好一個優秀的元件,一個優秀的元件應該具備什麼品質呢?
● 從需求角度出發
○ 當接到一個需求之後,應該第一時間去理解需求。考慮需求的本質與後續迭代可能會產生的變化。從而再去設計元件,以便應對需求的持續更新
● 從UI設計稿角度出發
○ 在透過程式碼還原設計稿之外,還需要考慮好元件樣式的相容性,不同螢幕尺寸的適配性,文案長短,異常資料顯示,預設頁展示等等
● 從使用者角度出發
○ 開發完一個元件,往往是需要提供給團隊的其它成員或者是自己使用的。這裏用上很喜歡的一句話「程式碼只是能友好的執行在機器上,但最終是寫給人看的」
○ 要以人為本,多為元件的使用者著想。想想別人在使用該元件的時候,心裏會不會罵娘,一段時間後自己在回過頭來看這個元件的程式碼,是否能看得懂
● 從元件自身角度出發
○ 元件本身要經過足夠多的測試,以確保元件能夠在不同場景下穩定執行
○ 對外暴露的api配置要儘量精煉且滿足功能
○ 對外暴露的api以及元件關鍵程式碼處需留下注釋或者api文件
○ 具備一定的拓展性和維護性,以確保使用者能在不修改原始碼的情況下實現一些定製化需求
○ 具備極強的易用性,簡單性。別讓元件的使用成本過高心智負擔過重
○ 對入參有一定的包容性,對出參有一定的健壯性。對一些引數型別,引數值做兜底與相容處理,對出參同樣要保持穩定,必要時給出相應的異常描述以便排查問題
○ 元件需要具備一定的靈活性,做到像介面一樣即插即用
○ 無副作用,無不良依賴。儘量避免與其他業務耦合,職責單一
○ 具備極強「普適性」要能最大程度的與其他元件組合使用,且不造成汙染
結束語
不難看出,不論是模組化還是元件化,其本質都是基於物件導向思想開發。在程式碼中多使用物件導向的思想,能使得我們的程式碼結構,組織邏輯,優雅程度更上一層樓。許多的設計模式看似高深,在理解了物件導向之後,再看這些設計模式就會有一種原來如此,恍然大悟的感覺。行走於江湖,修得此心法,必將突破天元境!