當 Vue 遇上 CSS variables
自從上個月 iOS 的專案收掉,公司便讓我去玩些 IoT、愜意地寫寫前端,趁還有記憶紀錄些比較有趣的議題…
先上最後效果圖:
需求主要是希望根據元件參數,切換不一樣的顏色。
過去類似的案例回顧
剛好在前陣子申請研究所時寫的個人簡歷的網頁有做一個主題切換的功能:
當時的邏輯大略是透過右上兩個 button 改變控制主題的布林值,並在 HTML 中透過布林值判斷此時該給予的 class,程式碼約略如下,
.contents.col-sm-8 .name(:class='isLightMode ? "text-main-dark" : "text-main-light"') 鄭羽霖 hr(:class='isLightMode ? "border-main-dark" : "border-main-light"') .education 臺灣大學土木工程學系 四年級 .job iOS 軟體工程師 @ 衛武資訊 .bio(:class='isLightMode ? "text-dark" : "text-light"')
而這次一開始也是打算這麼做,但這次比較特殊的一點在這個元件有用到 animation 跟 keyframes 兩個屬性,照上次的做法就得創根據不同類別創建複數個 keyframes 和 class ,並且其中大約只有幾個屬性是需要修改的,因此這個寫法並不太實際。
@keyframes signalWave { 0% { box-shadow: 0px 0px 0px 0px rgba($oriange, 0), 0px 0px 0px 0px rgba($oriange, 0), 0px 0px 0px 0px rgba($oriange, 0), 0px 0px 0px 0px rgba($oriange, 0) } 25% { box-shadow: 0px 0px 0px 10px rgba($oriange, 0.2), 0px 0px 0px 10px rgba($oriange, 0), 0px 0px 0px 10px rgba($oriange, 0), 0px 0px 0px 10px rgba($oriange, 0) } ...
觀察一下不難發現,不管上次還這次 class 之間的差別其實就是顏色的色碼而已,因此試著往變數的方向思考便找到 CSS variables。
CSS variables
Vue 透過 computed, v-bind:style 屬性本身就能夠把 js 變數傳進 style 裡,因此便試著在 computed 創建一個 cssProps 的變數,
export default { ... computed: { cssProps: function() { return {
'--color': '255, 0, 0' }
}
}
}
※註:CSS variables 必須以” — ”開頭。
再透過 :style 將變數傳進 CSS 中,
div(:style='cssProps')
CSS 便可正常的使用變數,
@keyframes signalWave { 0% { box-shadow: 0px 0px 0px 0px rgba(var(--sensor-color), 0), 0px 0px 0px 0px rgba(var(--sensor-color), 0), 0px 0px 0px 0px rgba(var(--sensor-color), 0), 0px 0px 0px 0px rgba(var(--sensor-color), 0) } 25% { box-shadow: 0px 0px 0px 10px rgba(var(--sensor-color), 0.2), 0px 0px 0px 10px rgba(var(--sensor-color), 0), 0px 0px 0px 10px rgba(var(--sensor-color), 0), 0px 0px 0px 10px rgba(var(--sensor-color), 0) } ...
※其中這裡有個雷點是變數傳入的色碼若要使用 rgba() 這個屬性就不能使用 hex 碼,而必須使用 rgba。
結論
使用 CSS variables 搭配 Vue computed, v-bind 有什麼好處?
- 框架跟邏輯分離,程式碼易讀性較高,方便改寫、維護。
- 變數集中在 computed,易於跟 Vuex、props、或 slot 作搭配。