Skip to content

模板語法與指令

重新認識 Vue.js: 008 天絕對看不完的 Vue.js 3.x 指南

上一節我們用 {{ }} 把資料顯示到畫面上。不過實際開發時,畫面不只需要顯示文字,也會需要綁定屬性、切換 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:altv-bind:srcv-bind:alt 的縮寫。當 imageUrlimageAlt 改變時,對應的 HTML 屬性也會跟著更新。

指令的基本形狀

指令通常可以拆成幾個部分:

html
<a v-bind:href="url">官方網站</a>
<button v-on:click="submit">送出</button>
  • v-bindv-on 是指令名稱。
  • hrefclick 是參數,代表這個指令作用在哪個屬性或事件上。
  • urlsubmit 是 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 補齊。