嗨各位,Tailwind 篇結束了,
不知道會不會有人敲碗更多呢?
還想知道更多的話也沒有問題~
不過今天要進入全新的篇章!
要說為什麼的話 ...
因為要想讓 Tailwind 能夠發揮最佳效用的話
那麼搭配前端框架
是再適合不過啦!
其實在 Day 14 「阿嬤的裹腳布」 - 提取成元件篇中我們就有提過,要想不取抽象的 class 名稱、且想要設計與視覺一致的話,切分成前端框架的元件是你最好的選擇。
因為做成元件後不但可以大量的重複使用
,
還可以運用一些變數
、條件判斷
等讓樣式做切換,
可以讓你的設計更加的靈活!
而前端框架無論是 Vue、React、Angular 都行,
在切版概念上是可以一併套用
的,
元件運作邏輯也基本能相通,
所以沒有說一定要使用哪一套框架哦!
只是兔兔會選擇使用 Vue ,
是因為 Vue 被認為是最好上手的框架,
同時也是兔兔相對最熟悉的框架
(不會其它的就說不會,說什麼相對最熟悉咧)
開場廢話說夠多了,那我們就開始囉!
雖然是 Vue 篇,但不會只講 Vue 的!
因為畢竟是主題是 Tailwind 呀!
所以我會更著重在兩者之間的關係與配合。
(而且 Vue 這個主題肯定被講到爛了)
Vue 自稱為漸進式
的 js 框架,
而為什麼要說是漸進式呀?
因為用多用少都好用!
沒錯,從 CDN 引入只用部分功能,
一直到完全用它的 CLI 來完成專案,
無論是哪個階段你都能體會到它所帶來的方便。
其實也並非說純 js 或 jQuery 不好不方便,
甚至 jQuery 還給予很多語法糖
,
但尤其在開發應用而非靜態畫面時,
最令人覺得痛苦的地方就是:資料的互動
。
所謂資料的互動是指從將資料顯示在畫面之上,並從畫面中取得資料;或者是說從相對應的動作如按按鈕、輸入文字、切換選項到更改網站主題等等都算。
那為什麼說在做資料互動時會令人痛苦?
以最陽春的 todoList 舉例:
<input type="text" id="textbox" />
<button onclick="add()">新增</button>
<ul id="todolist">
<!-- 待辦事項 -->
</ul>
<script>
function add() {
const textbox = document.getElementById("textbox")
const todolist = document.getElementById("todolist")
if (textbox.value!=="") {
todolist.innerHTML += `<li>${textbox.value}</li>`
}
}
</script>
做了簡單的防呆,按下新增時可以新增待辦事項。
但你需要為了獲取這些元素和資料,你必須幫它們想一大堆 id,然後再透過那些 id 取去取得資料,還要再自己撰寫顯示到畫面上的語句。
我們來看看 Vue:
<div id="app">
<input type="text" v-model="text" />
<button @click="add()">新增</button>
<ul>
<li v-for="item in todolist">
{{ item }}
</li>
</ul>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data() {
return {
text: "",
todolist: []
}
},
methods: {
add() {
if(this.text!=="") {
this.todolist.push(this.text)
}
}
}
}).mount('#app')
</script>
雖然看起來整段長了很多,但大部分都是 Vue 預設的架構。
我們把重點聚焦到 vue 的 add( ) 函數上:
// vue.js
add() {
if(this.text!=="") {
this.todolist.push(this.text)
}
}
函數內的處理變簡單了,只是單純地在操作變數內容
,
我們只需要在元素上綁定變數,
剩下的從資料到畫面、從畫面到資料框架會自己安排妥當。
如果像是做每次都要撈 API 取得最新資料並放上畫面,
那麼不用前端框架會讓你耗費非常多的時間,
才只能完成功能的一小部分。
其實不見得要到前端框架,Tailwind 只要能配合 js 整理起來讓結構重複使用,那麼都是方便的;而且用 js 還能很好的幫 tailwind 的語法分類。
拿我們之前的三個 box 元件來說:
<div class="flex justify-evenly p-10 focus-within:bg-green-100 group">
<box class="box bg-red-500 hover:bg-red-400 ring-red-300" tabindex="0">
1
</box>
<box class="box bg-blue-500 hover:bg-blue-400 ring-blue-300" tabindex="1">
2
</box>
<box class="box bg-purple-500 hover:bg-purple-400 ring-purple-300" tabindex="2">
3
</box>
</div>
我們可以用 js 改寫一下:
<div
id="main"
class="flex justify-evenly p-10 focus-within:bg-green-100 group"
>
<!-- 在這裡用 js 動態插入元件 -->
</div>
<script>
/* 把 box 元素一到 function 內當字串返回,
* 用變數決定使用哪個顏色的 class
* 以及用變數決定 box 的內容
*/
const boxCreator = (number, color) => {
const boxStyle = "bg-gray-500 focus:ring-4 group-hover:text-gray-600 font-bold flex justify-center items-center rounded-md cursor-pointer outline-none w-20 h-20 text-3xl text-white"
let colorClasses = ''
if(color==='red') {
colorClasses = 'bg-red-500 hover:bg-red-400 ring-red-300'
}
else if(color==='blue') {
colorClasses = 'bg-blue-500 hover:bg-blue-400 ring-blue-300'
}
else if(color==='purple') {
colorClasses = 'bg-purple-500 hover:bg-purple-400 ring-purple-300'
}
return (
`<box class="box ${colorClasses}" tabindex="${number}">
${number}
</box>`
)
}
// 獲取 main 區塊
var main = document.getElementById('main')
// 定義三個 box 的內容
const boxes = [
{number: 1, color: 'red'},
{number: 2, color: 'blue'},
{number: 3, color: 'purple'},
].forEach((box) => {
// 透過迴圈,呼叫 boxCreator 來產生方塊
main.innerHTML += boxCreator(box.number,box.color)
})
對這個內容有興趣的人,可以到這裡看範例程式
這樣看起來是很麻煩,但靈活多了。
不過這樣就能把 Tailwind 的語法切開,
相同部分也能製成元件一再利用。
不過這麼做終究是很醜又很麻煩,
一定還有更漂亮的做法吧?
有,讓我們看看 Vue 的版本。
如果是像剛剛做成相同功能的元件的話,
Vue 可以這樣做!
這個是單獨只有 Box 的元件:
<!-- Box.vue -->
<template>
<div
:class="[
[
'w-20 h-20 bg-gray-500 rounded-md',
'focus:ring-4 group-hover:text-gray-600',
'font-bold text-3xl text-white',
'flex justify-center items-center',
'cursor-pointer outline-none'
],
(color==='red') && 'bg-red-500 hover:bg-red-400 ring-red-300',
(color==='blue') && 'bg-blue-500 hover:bg-blue-400 ring-blue-300',
(color==='purple') && 'bg-purple-500 hover:bg-purple-400 ring-purple-300'
]"
:tabindex="number"
>
{{ number }}
</div>
</template>
<script>
export default {
name: "Box",
props: ["number", "color"]
}
</script>
元件做完之後,然後在頁面中使用:
<!-- main -->
<template>
<div class="flex justify-evenly p-10 focus-within:bg-green-100 group">
<!-- 用迴圈依照每一筆 Box 資料產生元件 -->
<box v-for="item in Boxes" v-bind="item" />
</div>
</template>
<script>
export default {
data() {
return {
// 定義三個 box 的內容
Boxes: [
{number: 1, color: 'red'},
{number: 2, color: 'blue'},
{number: 3, color: 'purple'},
]
}
},
components: {
Box
}
}
</script>
如果懂得切分元件,做起來會輕鬆非常多!
因為重複或是變化性的部分拆出來,
不但元件各自有各自的邏輯,
畫面也會清晰很多,
不會一下子看到一大堆的 Tailwind 語法,
然後 js 又寫的一長串。
真的是好處多多多!
其實 Vue 和 Tailwind 的關係也算密切,除了作者之間有互動之外,Vue 的作者尤雨溪也蠻肯定 Tailwind 的做法
,像是 Tailwind 簡體中文的文件就是 Vue 的作者架起來的。 (而繁體中文就是我們了!)
其中有一個由 Tailwind 官方團隊主導的計劃,雖然這個東西還在發展中,我覺得非常有趣,叫做 Headless UI。
根據 Github 上的敘述,HeadlessUI 是:
A set of completely unstyled, fully accessible UI components, designed to integrate beautifully with Tailwind CSS.
摁,簡單的來說就是,他們設計了一些基本符合 a11y 無障礙規範
、且已經具有元件操作邏輯
的 UI 元件庫。
然後特別的是,
這些元件並沒有附帶任何外觀樣式
,
也就是說外觀樣式要讓你用 Tailwind 來完成。
「兔兔,這有甚麼好處?」
哇!這個好處很大呢~
它很好的做到元件的外觀樣式與邏輯上的解耦合
。而且如果要從 0 開始讓元件設計符合無障礙規範,要考慮的東西太多了!
然後這個 HeadlessUI 和 Vue 有什麼關係我好像還沒說到。
就是 HeadlessUI 預設是給 Vue 和 React 使用,直接導入專案之中,再客製化樣式就完成元件了~
兔兔我真的覺得這是一個非常好、非常酷的概念!
那今天就是這樣啦!
說是介紹 Vue,
好像也沒有講到很多 Vue 齁 XD
因為主要是談談為什麼要用 Vue,以及用前端框架配合 Tailwind 的好處。畢竟後面就要開始使用了,還是要知道它們之間的互動關係,和到底能做到什麼事情!
關於兔兔們:
( # 兔兔小聲說 )
有人注意到,
昨天兔兔什麼都沒說嗎?你說我有說?
那你肯定沒有仔細看!!昨天的明明就是
「免(ㄇ一ㄢˇ)免(ㄇ一ㄢˇ)小聲說」!!!