iT邦幫忙

2021 iThome 鐵人賽

DAY 17
2
Modern Web

排版神器 Tailwind CSS~和兔兔一起快速上手漂亮的元件開發!系列 第 18

Day 17:「我們,是好朋友哦~」- Vue 簡介

Day17-Banner

嗨各位,Tailwind 篇結束了,
不知道會不會有人敲碗更多呢?

還想知道更多的話也沒有問題~
不過今天要進入全新的篇章!

要說為什麼的話 ...

因為要想讓 Tailwind 能夠發揮最佳效用的話
那麼搭配前端框架是再適合不過啦!

其實在 Day 14 「阿嬤的裹腳布」 - 提取成元件篇中我們就有提過,要想不取抽象的 class 名稱、且想要設計與視覺一致的話,切分成前端框架的元件***是你最好的選擇***。

因為做成元件後不但可以大量的重複使用
還可以運用一些變數條件判斷等讓樣式做切換,
可以讓你的設計更加的靈活

而前端框架無論是 Vue、React、Angular 都行,
在切版概念上是可以一併套用的,
元件運作邏輯也基本能相通
所以沒有說一定要使用哪一套框架哦!

只是兔兔會選擇使用 Vue ,
是因為 Vue 被認為是最好上手的框架,
同時也是兔兔相對最熟悉的框架

(不會其它的就說不會,說什麼相對最熟悉咧)

開場廢話說夠多了,那我們就開始囉!
 

carrotPoint 沒有主角光環的主角

雖然是 Vue 篇,但不會只講 Vue 的!
因為畢竟是主題是 Tailwind 呀!
所以我會更著重在兩者之間的關係與配合。

(而且 Vue 這個主題肯定被講到爛了)

Vue 自稱為漸進式的 js 框架,
而為什麼要說是漸進式呀?

因為用多用少都好用!

沒錯,從 CDN 引入只用部分功能,
一直到完全用它的 CLI 來完成專案,
無論是哪個階段你都能體會到它所帶來的方便
 

carrotPoint 是時候,該踏入前端框架了吧?

其實也並非說純 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 取得最新資料並放上畫面,
那麼不用前端框架會讓你耗費非常多的時間,
才只能完成功能的一小部分。
 

carrotPoint 提取成 js 元件

其實不見得要到前端框架,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 的版本。
 

carrotPoint 提取成 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 又寫的一長串。
真的是好處多多多!
 

carrotPoint 相輔相成

其實 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 的好處。畢竟後面就要開始使用了,還是要知道它們之間的互動關係,和到底能做到什麼事情!
 

carrotPoint 給你們的回家作業:

  • 今天放假一天嘿,沒有作業
  • 還是你想寫作業,我也能出給你哦!
     

關於兔兔們:


 


( # 兔兔小聲說 )

有人注意到,
昨天兔兔什麼都沒說嗎?

你說我有說?
那你肯定沒有仔細看!!

昨天的明明就是
「免(ㄇ一ㄢˇ)免(ㄇ一ㄢˇ)小聲說」!!!


上一篇
Day 16:「寶藏,都藏在那裡了!」- Tailwind JIT 模式
下一篇
Day 18:「極速開發」- Vitawind
系列文
排版神器 Tailwind CSS~和兔兔一起快速上手漂亮的元件開發!32

尚未有邦友留言

立即登入留言