2020 年 10 月 17 日,我正式釋出了 Fantastic-admin 這款基於 Vue 的中後臺管理系統框架。在這兩年多的時間裡,我陸續寫了幾篇我在開發這套框架中的一些心得和技術總結:
但是今年,有大半年的時間我幾乎銷聲匿跡,沒有產出一篇文章。除了一直在維護和迭代框架外,我也在思考一個問題,那就是:
如何才能做好一款管理系統框架?
這是「VUE後臺管理系統模板」網站上整理的一些相對做得比較出色,或者說有一定知名度的框架。當然這也只是冰山一角,如果去 Gitee 或者 Github 搜尋 「後臺」 「admin」 等關鍵詞,你還能發現更多。似乎寫一個後臺框架對前端開發來說,有手就行?
確實,一個標準的後臺管理系統,大部分基礎功能是相對統一的,因為它不像C端產品需要高度客製化化。一個側邊或者頭部導航欄,通過設定自動生成;再預設幾套主題,方便切換;然後寫幾個通用模組,比如使用者管理、角色管理、字典管理;最後再加個登入頁,完善下許可權控制,基本就大功告成了。
要實現這些難麼?不難,對前端來說,確實有手就行。這也促使很多開發者選擇自己寫,寫完有興致的還會推廣宣傳一番,反饋好就繼續維護,沒啥反饋可能就逐漸變成了一個自用框架或者棄坑了。
這也是為什麼網上有如此多後臺框架的原因,因為一直有新的框架出現,也有大量框架已經幾個月,甚至超過半年時間未更新,頗有一種「你方唱罷我登場」感覺。
迴歸到主題,既然要做好一款管理系統框架,那誰來定義這個「好」呢,是客戶嗎?是,但又不全是。
任何一款技術框架或產品,最終一定是服務於客戶、服務於業務的,但做為一款管理系統框架,我認為更多還是服務於開發者,讓開發者用更少的時間,完成客戶或業務需求,那就是一款好的管理系統框架。
但是一個有手就能寫的框架,要讓開發者選擇使用你的,而不是自己去寫,想必肯定不是實現上面那些功能那麼簡單,那要如何服務好開發者呢?
既然確定是給開發者服務,那就需要確定開發者的痛點。好在我本身也是開發者,在公司內部業務開發中就有實際在使用,所以開發中的痛點還是比較好找的,無非以下幾點:
針對以上整理的幾點,下面我會用幾個實際的例子來介紹下我是怎麼為開發者提供服務的,或者說我是怎麼服務自己的。
畢竟只要我自己覺得用得爽了,其他開發者的使用體驗也肯定不會太差,當然前提是拔高自我要求,以「人無我有,人有我優」做為目標。
這個痛點是相對比較容易解決的,因為市面上各種 UI 庫已經能滿足大部分的業務使用需求了,我只是做了一些二次封裝或補充。
比如在 Element Plus 的 Cascader 元件基礎上,封裝了省市區街道聯動元件,方便實現二級、三級和四級的選擇聯動:
再比如在 Element Plus 的 Upload 元件基礎上,封裝了圖片上傳元件,提供了多圖排序、多圖預覽、檔案型別和數量限制等特性:
除了對 Element Plus 進行一些二次封裝外,我還補充了一些元件,比如趨勢標記元件:
還有搜尋面板元件:
當然不僅僅是上面介紹的這些,更多可以存取 演示站 進行檢視。
我想說的就是,通用業務元件,是框架比較容易解決的一個痛點,因為它肉眼可見,通過原型圖或設計稿,找出一些頻繁在多個業務模組中出現的功能,就可以考慮是否可以封裝成元件,從而減少開發者自己去實現的時間。
後臺系統裡,一定有一些模組在介面、操作邏輯上是高度相似的,比如各個模組裡的列表頁,它們都有搜尋功能、資料展示、分頁功能。但又不完全一樣,比如資料來源、搜尋項、列表展示欄位都不一樣。
對於這種場景,我的做法是通過框架預設的目標,搭配互動式的指令去生成對應的檔案。小到元件和單頁面的模板,大到整個模組(包含列表頁、詳情頁、新增、編輯、刪除功能一應俱全),都可以通過幾個指令快速生成,如下圖:
當然開發者也可以根據具體業務場景,自行擴充套件需要生成的模板。
這一塊的痛點,更多體現在框架自身的能力上,也是我認為決定框架是否好用中最大的因素。
因為上面提到了兩個痛點,即使框架做得不到位,開發者也能自己想辦法去解決。業務元件少可以自己寫,或者找三方別人寫好的元件;頻繁拷貝程式碼也不是多大的問題,開發者可以藉助編輯器的程式碼片段功能,或者其他方式去提高效率。
但一些稍微特殊的場景下,如果框架本身沒有考慮到,那需求只能向框架妥協,畢竟不是所有開發者都有能力去完整閱讀框架原始碼,並進行二次開發客製化功能。
說了這麼多,可能大家還不清楚到底有哪些特殊場景,這裡我舉幾個我遇到的:
大家可以對比下現在正在使用的框架是否能滿足這些場景下使用,也可以留言分享一些其他業務場景
導航欄是個必備的功能,尤其是這種分欄佈局的導航(主導航+次導航),既然有分欄導航,那就會有次導航能否隱藏的場景,效果如下:
我的做法是通過兩個獨立的設定項組合使用,實現了這一場景,分別是 切換主導航時自動跳轉到次導航裡第一個欄目路由
和 次導航只有一個欄目時自動隱藏
。
分頁的實現是通過路由切換來實現的,每存取一個路由就會增加一個分頁。
但有的場景需要對分頁進行合併,比如反覆從列表頁開啟不同條目的編輯頁,因為每個編輯頁的路由不同,所以對應也會生成多個分頁,這時候就希望能將所有編輯頁的分頁合併成一個,效果如下:
既然有編輯頁合併的場景,那也會有列表頁和編輯頁合併的場景,比如同個模組下,不管是列表頁,還是編輯頁,或者其他同屬於該模組下的頁面,都希望能合併成一個分頁,效果如下:
這塊我的做法是提供了一個合併規則的設定項,預設不合並,同時支援 根據路由name進行合併
和 根據activeMenu進行合併
兩條合併規則,分別對應了上面兩個場景,具體設定可參考檔案介紹。
在瞭解這個場景前,我們先要知道什麼是頁面快取,就是當用戶離開當前頁面後,再返回該頁面,需要復原離開時的所有狀態,這就是頁面快取。
頁面快取是一個比較常見的場景,部分框架也提供了支援,但按需快取,也就是根據離開並存取的目標頁面,判斷是否需要對當前頁進行快取,舉個例子:
假設 A 頁面的快取規則是,如果離開並存取 B 頁面則進行快取,存取其他頁面則不快取;或者只有離開並存取 B 頁面不快取,存取其他頁面則都需要快取。
如果是上面假設的這兩個場景,按照大部分框架提供的能力(即在路由設定裡提供一個頁面是否開啟快取的設定項),可能就不一定能滿足了,因為頁面快取只提供了兩種狀態,即始終快取和始終不快取。
而我的做法是分別提供了 cache
和 noCache
兩個設定項,開發者可以對 cache
設定 true/false 值以滿足頁面始終快取或始終不快取的場景,也可以設定路由的name,實現精細化快取控制,還是拿上面兩個場景舉例,就可以輕鬆設定成:
// A 頁面離開並存取 B 頁面則進行快取,存取其他頁面則不快取
cache: 'b-route-name' // B頁面路由name
// A 頁面只有離開並存取 B 頁面不快取,存取其他頁面則都需要快取
cache: true,
noCache: 'b-route-name' // B頁面路由name
更多細節可參考檔案介紹。
這一痛點的根本原因其實是上一個痛點造成的,因為能力少,所以能暴露出的內部方法就不多,所以能提供的 API 自然也就少了。
這裡我就介紹幾個簡單的 API ,大家可以點預覽連結看實際效果:
import useMenu from '@/utils/composables/useMenu'
const { switchTo } = useMenu()
switchTo(index)
import useMainPage from '@/utils/composables/useMainPage'
const { reload } = useMainPage()
reload()
import useMainPage from '@/utils/composables/useMainPage'
const { maximize } = useMainPage()
// status: true / false
maximize(status)
有時候,我們需要在某個頁面顯示自定義的標題,而不是 meta.title
欄位,比如在編輯使用者的頁面,顯示當前使用者的名稱。
import useSettingsStore from '@/store/modules/settings'
const settingsStore = useSettingsStore()
onMounted(() => {
settingsStore.setTitle('測試標題')
})
提供了開啟、關閉、檢驗等 API 。
寫到這裡,想扯點題外話。
今年的某個時間,我突然對「程式設計師轉行,最適合轉產品經理」這句話有了更多認同感。而在程式設計師這個大類裡,我認為前端開發是其中尤為適合轉產品經理的。
因為大部分客戶不在乎你用什麼技術,他們只看中「外表」,像介面是否好看,操作是否合理,動效是否流暢,而前端開發大部分日常工作內容就是在和這些打交道。當接觸了足夠多的業務需求,就越瞭解客戶想要的是什麼,就能在下個業務需求裡快速找出其中的痛點或者不合理的地方,並提供一個相對成熟的解決方案,這同時也是一個產品經理所應該具備的能力和經驗。
就像我寫的這款管理系統框架,這一年我不滿足於堆砌新特性,而是在此基礎上思考怎麼更好的去服務使用我這套框架的開發者,不僅滿足他們的需求,還要讓他們用得舒適,正如 Fantastic-admin 官網首頁的標語——「開箱即用,提供舒適開發體驗」。
感謝大家閱讀到這裡,希望文中我的拙見能給大家帶來一些啟發。