雖然 HTML / CSS / JavaScript 為 Web 三劍客,但 Preprocessor 出現後,CSS 與 JavaScript 已經有不同寫法,如 SCSS、TypeScript,事實上 HTML 也有 Preprocessor:Pug,可寫出更精簡的 HTML。
Version
Pug 3.0.2
History
Pug 並不是什麼新技術,Pug 前身為 Jade,早在後端 render 時代,Node + Express + Jade 已為標準組合,Jade 為 template engine。
在 Vue 使用 Pug 只使用其一小部分語法,template engine 仍使用 Vue,且主要是為了 搭配 Tailwind CSS 。
Why Pug ?
Pug 除了是 template engine 外,還大幅改變了 HTML 語法:
- 取消 HTML 需要 close tag,使 codebase 更為精簡
- 可直接以
.
使用 CSS class,這對 Tailwind CSS 尤其方便 - 可省略
<div>
直接使用 CSS class,使 codebase 更為精簡
簡單來說,Pug 可視為 better HTML,尤其適合搭配 Tailwind CSS。
Attribute
Abbreviation
以 Pug 使用 attribute。
<template lang='pug'>
a(href='https://www.google.com') Google
</template>
第 2 行
a(href='https://www.google.com') Google
相當於
<a href="htts://www.google.com">Google</a>
- HTML attribute 改用 JavaScript 習慣的
()
表示, String 也改用 JavaScript 慣用的 single quote - 並不需要 close tag,比 HTML 更為精簡
- tag 與 content 以 space 分開即可
Vue
以 Pug 使用 event binding。
<template lang='pug'>
button(@click='onClick') Submit
div {{ msg }}
</template>
<script setup>
ref: msg = ''
let onClick = () => msg = 'Hello World'
</script>
第 2 行
button(@click='onClick') Submit
()
內也可使用 Vue 的 event binding
相當於
<button @click="onClick">Submit</button>
Multi Attribute
以 Pug 同時使用多個 attribute。
<template lang='pug'>
button(@click='onClick' autofocus) Submit
div {{ msg }}
</template>
<script setup>
ref: msg = ''
let onClick = () => msg = 'Hello World'
</script>
第 2 行
button(@click='onClick' autofocus) Submit
- 多 attribute 可使用如 HTML 以 space 隔開
button(@click='onClick', autofocus) Submit
- 也可如同 JavaScript 以
,
隔開
相當於
<button @click='onClick' autofocus>Submit</button>
Self Closing
以 Pug 使用 self closing 的 tag。
<template lang='pug'>
input(v-model='name')/
div {{ name }}
</template>
<script setup>
ref: name = ''
</script>
第 2 行
input(v-model='name')/
- 對於只有一個 tag 的 HTML,則以
/
結尾
/
必須緊接著)
不可有 space
相當於
<input v-model="name">
Class
Abbreviation
以 Pug 使用 CSS class。
<template lang='pug'>
a(href='https://www.google.com').text-2xl.text-red-500 Google
</template>
第 2 行
a(href='https://www.google.com').text-2xl.text-red-500 Google
- 只要以
.
就可使用 CSS class
相當於
<a href="htts://www.google.com" class="text-2xl text-red-500">Gogle</a>
Div
以 Pug 使用 div
實現 layout。
<template lang='pug'>
.flex.justify-center.h-96
.w-20.h-20.m-2 1
.w-20.h-20.m-2 2
.w-20.h-20.m-2 3
</template>
第 2 行
.flex.justify-center.h-96
.w-20.h-20.m-2 1
.w-20.h-20.m-2 2
.w-20.h-20.m-2 3
div
都用在 layout,造成 HTML 一堆div
,然這些div
本身必須搭配 Tailwind utility 才有效用,可省略div
直接使用 utility
Pug 因為 Tailwind 而顯得更為實用,這也是在 Vue 使用 Pug 主因
相當於
<div class="flex justify-center h-96">
<div class="w-20 h-20 m-2">1</div>
<div class="w-20 h-20 m-2">2</div>
<div class="w-20 h-20 m-2">3</div>
</div>
Special Character
以 Pug 使用含用特出字元的 utility。
<template lang='pug'>
.flex
div(class='w-4/12') 1
div(class='w-4/12') 2
div(class='w-4/12') 3
</template>
第 2 行
.flex
div(class='w-4/12') 1
div(class='w-4/12') 2
div(class='w-4/12') 3
- Tailwind CSS 有些 utility 使用特殊字元:
/
、[
、]
、#
,但可惜.
語法並不支援特殊字元,但(class='')
語法則可,因此若遇到使用特殊字元的 utility,則必須使用class
語法
相當於
<div class="flex">
<div class="w-4/12">1</div>
<div class="w-4/12">2</div>
<div class="w-4/12">3</div>
</div>
ID
以 Pug 使用 ID。
<template lang='pug'>
a#link(href='https://www.google.com') Google
</template>
第 2 行
a#link(href='https://www.google.com') Google
- 與 CSS 的 id 使用
#
一樣
相當於
<a id="link" href="https://www.google.com">Google</a>
Data Binding
以 Pug 使用 data binding。
<template lang="pug">
input(type='text', v-model='name')/
.text-red-500.text-2xl {{ name }}
</template>
<script setup>
ref: name = ''
</script>
第 3 行
.text-red-500.text-2xl {{ name }}
- 將 state 在最後 data binding
<template lang="pug">
input(type='text', v-model='name')/
.text-red-500.text-2xl.
{{ name }}
</template>
<script setup>
ref: name = ''
</script>
第 3 行
.text-red-500.text-2xl.
{{ name }}
- 或在 class 最後加上
.
,換行縮排後將 state 做 data binding
<template lang="pug">
input(type='text', v-model='name')/
.text-red-500.text-2xl
| {{ name }}
</template>
<script setup>
ref: name = ''
</script>
第 3 行
.text-red-500.text-2xl
| {{ name }}
- 或者換行後縮排使用
|
pipe operator 再接上 state 做 data binding
相當於
<template>
<input type='text' v-model="name">
<div class="text-red-500 text-2xl">{{ name }}</div>
</template>
<script setup>
ref: name = ''
</script>
White Space
以 Pug 實現 +
與 3
之間的 white space。
<template lang='pug'>
button(@click='onClick') +
| {{ count }}
</template>
<script setup>
ref: count = 0
let onClick = () => count++
</script>
第 2 行
button(@click='onClick') +
| {{ count }}
- 以
|
表示同一行,本來與之間就必須空一格,但為了多一個 white space 再多一個 space
相當於
<template>
<button @click='onClick'>+</button> {{ count }}
</template>
<script setup>
ref: count = 0
let onClick = () => count++
</script>
Conclusion
- Pug 原本為 template engine,但在 Vue 使用 Pug 只使用其 HTML 語法,template engine 仍使用 Vue,因此只能算使用 Pug 子集而已
- Pug 可任意組合
()
與.
位置,HTML 的 attribute 已經逐漸被 CSS 取代,attribute 目前多用在 component 的 v-model、event 與 prop,實務上會先使用()
,再使用.
- Pug 在 CSS class 無法使用特殊字元是唯一遺憾之處,在 Jade / Pug 時空背景不支援可以理解,畢竟沒人會特別使用特殊字元命名 class,但 Functional CSS 則不然,這使得 Pug 只能退而求其次使用
div
與class
語法,期待 Pug 日後能加以改進 - Pug 另外一個難點在於處理 white space,必須在
|
後面接兩個 space 才代表一個 white space,因為|
與 data 之間本來就需要一個 space