在這個三年的時間點上,也就是1100天,我打算繼續出來和大家嘮嘮,這一年我又做了些什麼事,或者說,如何把一款好的後臺框架變得通用? ...
前言
去年年底,我寫了一篇《如何做好一款管理後臺框架》的文章,這是我對開發 Fantastic-admin 這款基於 Vue 的中後臺管理系統框架兩年多時間的一個思考與總結。
很意外這麼一篇標題平平無奇的文章能收穫 30k 的瀏覽以及 600 多個收藏,似乎大家對這種非乾貨的文章也挺感興趣。於是在這個三年的時間點上(沒錯,也就是1100天),我打算繼續出來和大家嘮嘮,這一年我又做了些什麼事,或者說,如何把一款好的後臺框架變得通用?
題外話:如果你對我以前的文章感興趣,可以點我頭像進入主頁查看;如果你期待我以後的文章,也可以點個關註。
痛點
因為 Fantastic-admin 是基於 Element Plus 這款 UI 組件庫進行開發的,於是今年我陸陸續續被問到一些問題:
- 以後會有 Ant Design Vue 版本麽?會有 Naive UI 版本麽?會有 …… 版本麽?
- 我們公司/團隊有一套內部的 UI 組件庫,可以在 Fantastic-admin 里使用麽?會和 Element Plus 有衝突麽?
- 我們有一些老項目希望遷移到 Fantastic-admin 上來,但 UI 組件庫用的不是 Element Plus ,有什麼辦法麽?
- …
類似的問題一多,我也在思考一個問題:我的這款框架是不是被 Element Plus 綁架了?如果開發者在做技術選型的時候,因為 UI 組件庫不符合預期,而將我的框架篩掉,這是我不希望看到的結果。
基於這個潛在隱患,我開始計劃對框架進行轉型。
方案
方案一
既然開發者對 UI 組件庫有各自的偏好,我又想拉攏這部分開發者,那是不是多出幾套不同 UI 組件庫版本的就可以了呢?沒錯,這是我最開始冒出來的念頭。
我參考了一些同類產品的做法,儘管它們把不同 UI 組件庫版本做得很像,但在使用體驗過程中,還是會帶來操作上的割裂感。並且因為無法抹平不同 UI 組件庫在 API 上的差異,導致在框架功能上,不同版本之間也會有一些差異。
你可以分別對比左右或者上下兩張圖,包括左側導航欄的樣式、導航收起/展開按鈕的位置、右側項目配置中提供的功能等,都能明顯發現它們的差異。
雖然這可能不是什麼大問題,但我認為視覺風格上的統一是能幫助產品提高識別度的。就比如上面 4 款基於不同 UI 組件庫開發的後臺框架,雖然它們屬於同一個產品,但如果我不告訴你,你未必能通過圖片確定它們師出同門。
其次就是後臺框架提供的功能不統一,這裡面有一定的原因是因為 UI 組件庫導致的。試想一個場景,如果你要從 Element Plus 版本的後臺,遷移到 Ant Design Vue 版本的後臺,框架的配置文件是否能原封不動的複製過去?如果導航(路由)數據是後端返回的,數據結構能否保持完全一致,後端無需做任何修改?因為不同 UI 組件庫對菜單組件的使用方式是完全不同的,比如 Element Plus 是需要手動拼裝的,而 Naive UI 則是數據驅動的,只需要傳入一個樹形結構的數據給組件即可。如果數據結構無法保證一致,就會增加遷移和學習的成本。
最後就是我的一點私心,因為多一個 UI 組件庫的版本,勢必會占據我更多的業餘時間,如果同時維護 4、5 個版本,那我大概下班後的所有時間都要投入到其中,並且如果未來又有新的 UI 組件庫成為流行,那就又多一個版本的維護,這並不是一個可持續發展的方案。
方案二
既然上一個方案不符合我的期望,於是我開始思考,框架本身能不能不依賴這些 UI 組件庫?如果框架本身不依賴於三方的 UI 組件庫,那開發者不就可以根據需要自行引入想要的組件庫了麽。
就如上圖,主/次導航和頂欄是屬於框架的部分,而這部分其實並沒有用到太多 UI 組件庫提供的組件,以 Element Plus 舉例,我統計了一下目前 Fantastic-admin 用到的組件:
- Menu 菜單(主/次導航)
- Breadcrumb 麵包屑(頂欄)
- Popover 氣泡卡片(頂欄右側的工具欄)
- Dropdown 下拉菜單(頂欄右側的工具欄)
- Drawer 抽屜(應用配置)
- Message 消息提示
- Button 按鈕
- Input 輸入框
- Radio 單選框
- Select 選擇器
- Switch 開關
- …(等等表單類組件)
可以看到,雖然抽屜組件里用了很多表單類的組件,但這部分組件都是在應用配置里使用的,而應用配置這個模塊,主要是方便線上測試框架提供的各種功能,在實際業務開發中,是完全不需要這個模塊的。
所以初步算下來,後臺框架真正依賴於 Element Plus 實現的組件就只有 4 個:
- Menu 菜單
- Breadcrumb 麵包屑
- Popover 氣泡卡片
- Dropdown 下拉菜單
那我為什麼不找一些獨立的第三方插件替代呢?是的,這是我第二個方案,就是找一些獨立的插件替換 UI 組件庫中的組件。但問題也立馬迎面而來,就是偌大一個 Github ,居然找不到符合我需求和審美的插件。
比如菜單插件,我希望它和 Element Plus 里的菜單組件在功能上沒有太大差異,支持水平/垂直模式、支持摺疊收起、支持設置預設激活菜單、支持預設展開等。
比如麵包屑插件,或許是因為這個插件功能太簡單,並且大部分 UI 組件庫都有提供,在 Github 能搜到獨立的麵包屑插件很少,搜到的也基本上是 N 年前的上傳的,既沒有人維護,風格樣式也很醜。
這個方案似乎也行不通……嗎?
方案三
雖然方案二在實施的第一步就撲街了,但有一點思路還是正確的,就是讓框架本身不依賴於三方 UI 組件庫。既然網上搜不到合適的插件,那我為什麼不自己寫一個呢。
比如麵包屑,這是一個很簡單的功能,任何前端初學者應該都可以寫一個麵包屑組件。
而氣泡卡片和下拉菜單我沒有計劃自己寫,因為找到了一個還不錯的插件 Floating Vue,它由 Vue 團隊核心人員開發並維護,並且最重要的是它支持自定義樣式,意味著我可以將它魔改成想要的樣子,儘可能和我的框架在視覺風格上保持統一。
最後一個比較難啃的骨頭就是菜單,因為找不到合適的替代品,自己寫的話又比較有挑戰,雖然我有一點實現思路,但不多。當然最終還是決定自己寫一個,因為覺得三方 UI 組件庫這麼多,實在寫不出來我就去讀他們源碼,總不能每一個源碼我都讀不懂吧。
這 4 個組件的替換方案確定後,剩下就是抽屜組件和它裡面的一些表單組件了,這些要怎麼解決呢?這會我想到了 Headless UI ,它是完全無樣式的 UI 組件庫,通過與 Tailwind CSS / UnoCSS 集成使用,可以快速構建出屬於自己風格的組件。
但是 Headless UI 提供的組件非常有限,並不能覆蓋我需要的表單組件。不過它的設計給了我啟發。表單組件我並不需要非常複雜的功能,原生的表單控制項其實就能滿足我的使用需求,只是原生的樣式比較醜,和我想要的風格不統一,那我只需要給他們定製一套統一的風格就可以了,也就寫一套原子化的 CSS 樣式。
於是,方案敲定,開始實操。
實操
我決定從易到難開始處理,因為這樣在初期能快速看到進度推進,也避免一上來就被一個菜單功能卡住好幾天,甚至十幾天都沒有進展,打擊到自己的信心。
1. 麵包屑
和預期一樣,並沒有什麼難度,很輕鬆就實現了。只不過目前還是保持和 Element Plus 一樣的使用方式,就是需要手動拼裝,後期計劃改成數據驅動的使用方式。
2. 氣泡卡片 & 下拉菜單
這部分參考了 nuxt/devtools 中 Floating Vue 的自定義樣式,以及 nuxt/ui 中下拉菜單的樣式風格,最終形成了我自己滿意的風格
3. 抽屜
使用了 Headless UI 中的 Dialog 組件,因為它和抽屜組件有相同的交互方式,它們都是在遮罩層上展示內容,只不過 Dialog 更多時候是居中展示,而抽屜則是在左右兩側展示。
其次在使用過程中,發現 Headless UI 中的 Transition 組件是一個驚喜。雖然 Vue 本身就有提供 <transition>
組件用於處理過渡動畫,但有一個場景會比較難處理,官方的描述是:
This technique is needed when you want to coordinate different animations for different child elements – for example, fading in a Dialog's backdrop, while at the same time sliding in the contents of the Dialog from one side of the screen.
當您要為不同的子元素協調不同的動畫時,就需要使用這種技術,例如,在淡入對話框背景的同時,從屏幕的一側滑入對話框的內容。
這說的不就是抽屜組件麽?於是按照官方的示例,修改了整體風格,最終效果也就出來了。
4. 表單組件
之前的計劃是修改原生表單控制項的樣式,但在開發過程中發現會有一定的局限性。比如 <select>
無法控制彈出選項框的樣式,我的解決辦法就是用 Floating Vue 封裝模擬一個 select 組件。
同時也在開發過程中發現了一些被遺漏組件,於是邊做邊補,最終大概做了 10 多個組件。雖然看著不少,它們都秉持著最小可用的狀態。什麼意思呢?就是我不會給它們設計太多的 API ,因為它們的定位和三方 UI 組件庫不同,它們只要滿足框架本身使用即可,用不到的 API 不會進行開發。並且使用上也不會有太大負擔,如果不是對框架進行二次開發,開發者是可以完全不用關註這部分組件。
5. 菜單
菜單組件確實是個難啃的骨頭,我差不多用了 3 周的晚上時間去開發。
第一周,按照自己的思路徒手擼,做到一半卡殼,做不下去了;
第二周,開始看 Element Plus 、Naive UI 、Ant Design Vue 里菜單的源碼;
Ant Design Vue 的沒看懂,放棄;
Naive UI 的看到一半發現核心實現被作者封裝到 treemate 這個獨立包中了,雖然這個包是開源的,目的也是針對樹形結構的一體化解決方案。但我粗略看了一遍文檔,感覺有點大材小用,因為它有很多 API 我是用不到的,而我對菜單組件又有一些自己的想法,不確定是否它這個包能否滿足我的需求,放棄;
最後選擇看 Element Plus 的,通過在本地一點點列印數據,大概理解了實現思路,但組件遞歸調用,父子組件通過 provide / inject 傳遞數據和函數的方式,數據狀態的變動也是一層層向上級組件通知,直到通知到頂層組件,在我看來有點不太優雅,如果數據能統一在頂層組件里操作就好了。其次我的計劃是寫一個數據驅動的菜單組件,而不是像 Element Plus 需要手動拼裝的,所以雖然我大致看懂了 Element Plus 菜單組件是怎麼實現的,但在我自己實現的時候,還是有很大的不同,能參考的代碼並不多。
這部分的開發總結,我可能會在以後單獨寫一篇文章詳細說說,因為這部分也是整個方案中唯一的難點。
第三周,因為實現思路大致有了,所以開發上就沒有太多的卡殼,最終結果也還不錯,基本達到了我的需求。
同時因為組件完全可控,順帶解決了之前使用 Element Plus 菜單組件上無法解決的 bug ,比如當菜單收起時,彈出的懸浮菜單如果數量過多,超出屏幕高度,超出的部分就無法查看了,就像這樣:
但是現在則會有滾動條,使用體驗上更舒服。
驗證
至此,我的後臺框架已經擺脫對 Element Plus 的依賴,接下來就需要驗證一下是否可以方便的替換成其他 UI 組件庫。
我分別用 Ant Design Vue 、Arco Design Vue 、Naive UI 、TDesign 這四款熱度比較高的組件庫進行了驗證:
Ant Design Vue | Arco Design Vue | Naive UI | TDesign |
---|---|---|---|
結果還是很滿意的,都能夠順利替換,並且替換過程並沒有花費很多時間,一個小時內就可以替換成功。
由於登錄頁這個特殊的存在,替換組件庫後是需要對其用到的 Element Plus 組件進行手動修改的,這部分會比較花時間,因為會涉及到表單驗證之類的東西,不同組件庫的寫法差異還是比較大的。
詳細的替換步驟可以在 Fantastic-admin 官方文檔里找到。
回顧
讓我們重新看下一開始的痛點是否都解決了麽:
-
以後會有 Ant Design Vue 版本麽?會有 Naive UI 版本麽?會有 …… 版本麽?
雖然不會有,但可以自己動手,根據教程將預設的 Element Plus 替換成你想要的 UI 組件庫就可以了
-
我們公司/團隊有一套內部的 UI 組件庫,可以在 Fantastic-admin 里使用麽?會和 Element Plus 有衝突麽?
不會有衝突,現在可以徹底移除 Element Plus ,安裝並使用自己的 UI 組件庫
-
我們有一些老項目希望遷移到 Fantastic-admin 上來,但 UI 組件庫用的不是 Element Plus ,有什麼辦法麽?
可以用 Fantastic-admin 源碼先進行 UI 組件庫的替換,之後再將老項目的業務代碼逐部遷移
除瞭解決這些痛點,甚至還有新收穫:
-
幫助公司/企業打造視覺風格統一的產品,提高產品辨識度
大公司可能有不止一個項目團隊,不同項目團隊的技術偏好可能無法完全統一,導致開發的後臺長得也千變萬化。但即使在這種情況下,使用 Fantastic-admin 依舊可以保持整體視覺風格上的統一。
-
近乎於 0 的上手成本
因為後臺框架始終都只有一套,開發者不會因為切換 UI 組件庫後,要重新瞭解後臺框架的使用
-
維護成本更低,產品生命周期更長
這一點是對我自己說的,不管未來會出現多少個新的 UI 組件庫,我都不需要去新增一個版本進行單獨維護;或者 Element Plus 如果有一天停止維護了,我的產品也不會因此進入了死亡倒計時
總結
文章寫到這裡,差不多就結束了,雖然閱讀一遍可能只花了不到10分鐘,但為了做成這件事,我大概從今年 6 月份就開始構思了,也是花了蠻多的精力,所以很感謝你的耐心。
當一款產品做到第 4 個年頭,周圍大部分同類產品都進入到半停更的狀態,這一年裡我經常思考如何延長產品的生命周期,如何讓更多人來使用,而這篇文章就是對我自己今年的一個總結,也是一份答卷,希望大家能喜歡。
另外,Fantastic-admin V4.0 已經正式發佈,感興趣的朋友可以來看看,或許你的下一個項目,就可以用上了。
新博客地址hooray.github.io