很多人對於 Functional CSS 直覺印象就是 HTML 會帶一堆 CSS Class,事實上當 Component 觀念出現後,由於 Prop 也能用在 CSS,因此 CSS 就有了新的用法。
Version
macOS Catalina 10.15.6
WebStorm 2020.2
Vue 2.6.11
Tailwind CSS 1.6.0
Root Component
有兩個 button,各為 dark purple 與 light purple。
App.vue
<template>
<div class="flex">
<my-button color="darkPurple">Submit</my-button>
<my-button color="lightPurple">Submit</my-button>
</div>
</template>
<script>
import MyButton from '@/components/MyButton'
export default {
name: 'App',
components: {
MyButton
}
}
</script>
第 3 行
<my-button color="darkPurple">Submit</my-button>
<my-button color="lightPurple">Submit</my-button>
雖然看起來是兩個不同顏色 button,但實際上是同一個 MyButton
component,只是對 color
prop 指定了 darkPurple
與 lightPurple
不同值。
MyButton Component
MyButton.vue
<template>
<button type="button" :class="colorClass" class="inline-flex items-center px-4 py-2 border border-transparent text-sm leading-5 font-medium rounded-md focus:outline-none focus:shadow-outline-indigo transition ease-in-out duration-150">
<slot></slot>
</button>
</template>
<script>
let colorClass = function() {
return {
darkPurple: 'text-white bg-indigo-600 hover:bg-indigo-500 focus:border-indigo-700 active:bg-indigo-700',
lightPurple: 'text-indigo-700 bg-indigo-100 hover:bg-indigo-50 focus:border-indigo-300 active:bg-indigo-200'
}[this.color]
}
export default {
name: "MyButton",
props: [
'color'
],
computed: {
colorClass
}
}
</script>
第 2 行
<button type="button" :class="colorClass" class="inline-flex items-center px-4 py-2 border border-transparent text-sm leading-5 font-medium rounded-md focus:outline-none focus:shadow-outline-indigo transition ease-in-out duration-150">
<slot></slot>
</button>
MyButton
骨子還是使用 HTML 的 <button>
,將相同的 utility 留在 class
attribute 內,不同的部分綁定到 colorClass
computed。
第 8 行
let colorClass = function() {
return {
darkPurple: 'text-white bg-indigo-600 hover:bg-indigo-500 focus:border-indigo-700 active:bg-indigo-700',
lightPurple: 'text-indigo-700 bg-indigo-100 hover:bg-indigo-50 focus:border-indigo-300 active:bg-indigo-200'
}[this.color]
}
colorClass
computed 的實作很精彩,將要傳入的 darkPurple
與 lightPurple
放在 Object 的 key,將不同的 utility 放在其 value,直接使用 [this.color]
從 prop 比對出。
Conclusion
- 可將 Tailwind CSS 的 utility 視為 function,藉由 Function Composition 組合出想要的 style,並將相同的部分保留在
class
attribute,不同的部分則以 prop 傳入,最後使用 computed 選擇出不同的 utility 綁定 - 以前 CSS 與 JavaScript 可謂井水不犯河水,CSS 負責 style,JavaScript 負責 logic,但透過 component 與 utility 整合之後,可藉由 component 重新組合 utility,解決 CSS 重複的老問題
Reference
Adam Wathan, CSS Utility Classes and “Separation of Concerns”