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 给你们的回家作业:

  • 今天放假一天嘿,没有作业
  • 还是你想写作业,我也能出给你哦!
     

关於兔兔们:


 


( # 兔兔小声说 )

有人注意到,
昨天兔兔什麽都没说吗?

你说我有说?
那你肯定没有仔细看!!

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


<<:  Swift 新手-如何使用 Xcode 建立专案?记得先更新作业系统!

>>:  30-3 之软件架构设计原则 2 - OCP 开放封闭原则

从零开始学3D游戏开发:零件介面 Part.1 开始

这是 Roblox 从零开始系列,使用者介面章节的第五个单元,你将要学会如何开始在零件的表面上去设计...

【Day3】[资料结构]-链结串列Linked List

链结串列(Linked List)常用来处理相同类型资料,在不连续的记忆体位置,以随机的方式储存,由...

[Pytorch] torchvision.transforms()

torchvision.transforms() Transforms are common im...

Day18 Let's ODOO: Paper Format

今天我们来介绍Report paper format,有时候我们在生成report时候想要自己自定义...

WUSON的CISSP学习资源

Effective CISSP LINE公开群组 [http://line.me/ti/g/vqK...