Appearance
模板語法與指令
上一節我們用 {{ }} 把資料顯示到畫面上。不過實際開發時,畫面不只需要顯示文字,也會需要綁定屬性、切換 class、套用 style,甚至在少數情境中輸出 HTML。這些需求都會透過 Vue 的模板語法與指令完成。
什麼是指令?
Vue 指令是寫在模板上的特殊屬性,通常以 v- 開頭。它們會把 DOM 行為和響應式資料連起來。
vue
<script setup>
import { ref } from 'vue'
const imageUrl = ref('https://vuejs.org/images/logo.png')
const imageAlt = ref('Vue logo')
</script>
<template>
<main class="app">
<img :src="imageUrl" :alt="imageAlt" class="logo">
</main>
</template>
<style scoped>
.app {
padding: 2rem;
}
.logo {
width: 96px;
height: 96px;
}
</style>這裡的 :src 與 :alt 是 v-bind:src、v-bind:alt 的縮寫。當 imageUrl 或 imageAlt 改變時,對應的 HTML 屬性也會跟著更新。
指令的基本形狀
指令通常可以拆成幾個部分:
html
<a v-bind:href="url">官方網站</a>
<button v-on:click="submit">送出</button>v-bind、v-on是指令名稱。href、click是參數,代表這個指令作用在哪個屬性或事件上。url、submit是 JavaScript 表達式,會在目前元件的資料範圍內求值。
常用縮寫如下:
| 完整寫法 | 縮寫 | 用途 |
|---|---|---|
v-bind:href="url" | :href="url" | 綁定 HTML 屬性 |
v-on:click="submit" | @click="submit" | 監聽 DOM 事件 |
綁定 class
class 常會依狀態改變。Vue 可以用物件語法讓條件更清楚:
vue
<script setup>
import { ref } from 'vue'
const isActive = ref(true)
const hasError = ref(false)
function toggleActive() {
isActive.value = !isActive.value
}
</script>
<template>
<main class="app">
<p
class="message"
:class="{ active: isActive, error: hasError }"
>
這段文字會依狀態切換 class。
</p>
<button type="button" @click="toggleActive">
切換 active
</button>
</main>
</template>
<style scoped>
.app {
padding: 2rem;
}
.message {
color: #555;
}
.active {
color: #0f766e;
font-weight: 700;
}
.error {
color: #b91c1c;
}
</style>active: isActive 的意思是:當 isActive 為真,就加上 active class;否則移除它。
綁定 style
行內樣式也能透過物件綁定。建議使用 camelCase 屬性名稱,和 JavaScript 物件一致:
vue
<script setup>
import { ref } from 'vue'
const fontSize = ref(18)
const themeColor = ref('#2563eb')
function enlarge() {
fontSize.value += 2
}
</script>
<template>
<main class="app">
<p :style="{ fontSize: `${fontSize}px`, color: themeColor }">
這段文字會變大。
</p>
<button type="button" @click="enlarge">
放大
</button>
</main>
</template>
<style scoped>
.app {
padding: 2rem;
}
</style>若 class 或 style 的邏輯開始變複雜,通常會在 <script setup> 裡用 computed 整理,避免把判斷塞滿模板。computed 會在本章最後一節介紹。
動態參數
有時候,連要綁定的屬性名稱也可能來自資料。這時可以使用動態參數:
vue
<script setup>
import { ref } from 'vue'
const attributeName = ref('href')
const linkValue = ref('https://vuejs.org/')
</script>
<template>
<main class="app">
<a :[attributeName]="linkValue" target="_blank" rel="noreferrer">
Vue 官方網站
</a>
</main>
</template>
<style scoped>
.app {
padding: 2rem;
}
</style>:[attributeName] 會把 attributeName 的值當作屬性名稱。這種寫法不需要常用,但在寫彈性較高的元件或工具時會派上用場。
輸出 HTML:v-html
一般文字插值會自動跳脫 HTML,避免字串被當成真正的標籤執行。若確定內容來源可信,可以用 v-html 輸出 HTML:
vue
<script setup>
import { ref } from 'vue'
const trustedHtml = ref('<strong>這段文字會以粗體顯示</strong>')
</script>
<template>
<main class="app">
<p v-html="trustedHtml"></p>
</main>
</template>
<style scoped>
.app {
padding: 2rem;
}
</style>注意:不要用 v-html 顯示未信任內容
v-html 會把字串當作 HTML 插進頁面。如果內容來自使用者輸入、外部 API 或任何未經清理的來源,就可能造成 XSS 風險。
一般情況下,優先使用 {{ }} 顯示文字;只有在來源可信且確定需要 HTML 時,才使用 v-html。
其他內建指令
下面幾個指令不一定一開始就會用到,但先知道它們的定位即可:
| 指令 | 用途 |
|---|---|
v-once | 只渲染一次,後續資料變化不再更新該區塊。 |
v-pre | 跳過該元素與子元素的 Vue 編譯,常用於顯示原始 Mustache 語法。 |
v-cloak | 搭配 CSS 隱藏尚未完成編譯的模板,較常見於非建置工具情境。 |
v-memo | 記憶模板子樹,只有指定依賴改變時才重新更新。 |
模板語法先介紹到這裡。下一節,我們回頭處理前面已經出現好幾次的 @click,再把表單需要的 v-model 補齊。
