這段時間真的是一段漫長的旅程。這是一個用盡全力想要塞入所有資訊的系列,回頭看某些元件,儘管我一開始就預期這些元件需要處理的功能非常多,最終的篇幅還是讓我有點驚訝。
就像胡立曾在他的文章中提到的:「在寫作的時候,選擇什麼要講什麼不講也是一門技藝。」而這門技藝,我覺得我還需要花更多心力去學習掌握。
在專案規劃中,不論是使用現成的 UI Library 並自行進行魔改,或是自行撰寫每一個元件,這兩者都不是容易的事情。為你自己寫 Vue Component(s) 整個系列文章共實作了 27 個元件,內容涵蓋了前端開發常見的元件,實作部分也大量參考了 Element Plus、Vuetify、Nuxt UI 甚至 React 的 Material UI。如果想要深入理解 UI Library 如何實作這些元件,又或是有計劃在自己的專案中使用自己寫的元件,我相信這個系列一定會是非常有價值的參考資料。
在這整個系列中,有很大一部分的篇幅在處理於關於鍵盤操作的功能,我覺得一個好的網站,特別是後台系統,應該可以讓使用者幾乎不用到滑鼠、觸控板,單靠鍵盤就能完成所有的操作;有一部分是關於 SCSS 的使用技巧與 CSS 變數的組合應用,如果能活用 SCSS 或是 CSS 變數的話,就算元件擁有多樣的外觀組合,我們還是可以優雅的撰寫樣式並且確保最後生成的 CSS 檔案不會太過龐大;還有部分關於 HTML 標籤的選用,選用正確的 HTML 標籤不僅可以讓網頁更好的 SEO 效果,最棒的是依賴瀏覽器原生支援的功能可以讓我們省下很多複雜的程式處理;最後還有一些是關於無障礙設定的細節,大多數時候無障礙設定並不會太複雜,一些簡單的屬性標記就能讓更多使用者更好地理解網頁內容。我們都能理解無障礙網頁的重要,但我們也確實經常忽略這些小細節。
回顧一下這個系列介紹了哪些元件:
基礎與導航元件
資料與狀態顯示元件
表單元件
SSR
我真心希望這個系列能帶來一些影響,讓更多人願意嘗試理解元件的實作原理,甚至開始親自動手製作這些元件。但也因為對這個系列抱有很大的期望,不論在元件實作還是文章撰寫,都不自覺地塞入了很大量的資訊,甚至有點貪心。儘管後來我已刻意簡化部分內容以避免過度發散,仍然有些篇章會顯得較難理解。如果有不清楚的地方,歡迎與我討論,我非常想知道你們的想法。
這個系列雖然告一段落,但元件的迭代與進步是永無止境的。這是我第五次整理自己的元件庫,每次都經過一段時間的應用與微調,每一次迭代都融合了上一次的使用經驗加以改進琢磨,讓元件更強大、易用、好維護。
礙於時間,還有很多元件和細節想提及與挑戰,但未能在這個系列中提到。然而這就像專案開發,我們不可能等到元件百分之百完成才開始使用,所有元件都是不斷迭代、累積經驗、改進的過程。
自己做一套 UI Library 我覺得最大的好處就是彈性與自由,但其實最大的隱憂也是彈性與自由。
儘管自己維護了專案開發用的 UI Library,我認為功能上還是要有一定的取捨。每次整理元件時,我最糾結的問題之一是「這個功能是否應該由這個元件負責」,當然這個糾結遇到不同的專案,永遠會有不同的結論,呼應前面提到的:「在規劃元件的時候,選擇什麼功能需要這個元件被涵蓋什麼功能不管也是一門技藝」。
在前言時,有個段落是這樣寫的:
如果能有一套 UI Library 完全貼合專案需求,那就太好了。但現實總是殘酷的,幾乎沒有任何一個專案可以完全依賴某一套 UI Library 來滿足需求。更多時候,我們需要使勁地「魔改」,利用各種權重的 CSS 覆蓋 UI Library 原有的樣式,甚至用盡各種曲折離奇的黑魔法來讓 UI Library 變成我們想要的樣子。改到最後開始懷疑人生,想著自己寫可能還比較快,但頭已經洗下去了,只能摸摸鼻子繼續施展魔法。然後,那天 UI Library 更新時,我們又得重新來過。
難道為了專案長遠著想,我們真的就不該使用 UI Library 嗎?
我們選擇使用 UI Library 後,必然需要依照專案需求編寫 CSS 覆蓋元件的樣式,但怎麼調整才能讓元件更好維護?我自己會選擇多使用一層元件封裝,我這裡使用 Element Plus 的 <ElCheckbox>
與 <ElSwitch>
為例,我會分別封裝成 <AtomicCheckbox>
與 <AtomicSwitch>
元件並且提供一些樣式的覆蓋與介面的轉換。
AtomicCheckbox.vue
<script setup lang="ts">
import 'element-plus/es/components/checkbox/style/css';
import { checkboxEmits, checkboxProps, ElCheckbox } from 'element-plus';
const props = defineProps(checkboxProps);
defineEmits(checkboxEmits);
</script>
<template>
<ElCheckbox v-bind="props">
<slot name="default" />
</ElCheckbox>
</template>
<style lang="scss">
.el-checkbox {
// 這裡覆蓋樣式
}
</style>
AtomicSwitch.vue
<script setup lang="ts">
import 'element-plus/es/components/switch/style/css';
import { ElSwitch, switchEmits, switchProps } from 'element-plus';
const props = defineProps(switchProps);
defineEmits(switchEmits);
</script>
<template>
<ElSwitch v-bind="props">
<slot name="default" />
</ElSwitch>
</template>
<style lang="scss">
.el-switch {
// 這裡覆蓋樣式
}
</style>
可能平常不會覺得這樣有什麼好處,但如果遇到下列情境,有沒有多封裝這一層就會差蠻多的。
<ElCheckbox>
廢棄的屬性
<ElSwitch>
廢棄的屬性
在專案中使用到這些即將廢棄的 API,如果我們有多封裝一層,我們就可以在封裝的元件裡面解決這些問題,而不一定需要在每個地方都去調整。
不論選擇哪一種方式,為自己寫 Vue Component(s),或是繼續使用 UI Library,專案走到最後好不好維護,這一切其實都回歸管理問題。
這段旅程真的是非常漫長,真的太漫長了所以講第二遍。參加這次鐵人賽,從確定大方向到每個元件的資料收集與實作,從第一篇文章一路發到今天,前後將近五個月的時間,感謝所有啟發我、幫助我、陪伴我的每一位朋友。
首先要感謝《哎呀!不小心刻了一套 React UI 元件庫:從無到有輕鬆上手》這本書的作者 Taiming。為你自己寫 Vue Component(s) 這個系列受到他在 2022 年鐵人賽系列文章 30 天擁有一套自己手刻的 React UI 元件庫 的啟發,並在過程中也給了我許多經驗分享與鼓勵。
補充感謝 Alex 宅幹嘛 的 Alex,這是我當年初入門前端時會不斷 follow 的頻道之一,我有很多對於前端開發的價值觀是在一次又一次的直撥分享中被慢慢建立起來的,我會更偏好為自己寫 Vue Component 很大部分是受到他的影響,可以說沒有那段時間的影響,就不會有這個系列的誕生。
再來感謝這一段時間幫我仔細審稿並且給我重要回饋的 HANKSIE、Hans Tu 與 Rock,以及幫我製作這系列每篇文章封面的 麻糬貓,有他們的幫忙這個系列才能看起來更完整、更專業。
當然也要感謝我的另一半,感謝她在這五個月來的包容,體諒我因為每天趕鐵人賽而不小心忽略她。
最後,感謝看完這個系列的你們,光是能一篇一篇追到這裡已經是非常不容易的事情了。
如果喜歡這個系列文章,可以多多分享;如果有任何批評或建議,也非常歡迎。
也歡迎追蹤我的部落格與 GitHub,我會持續分享一些前端開發的心得與技術分享。
部落格:https://mini-ghost.dev/posts
GitHub:https://github.com/Mini-ghost
期待與大家交流。
內容超豐富的系列文👍
需要再找時間好好品嚐
恭喜大大完賽~
謝謝!也很期待 你的優先選擇是什麼?從 CSS 選擇器到優先級,深入解析與實用技巧 系列 順利完賽 🙌