本文 AI 產出,尚未審核

Vue 3 基礎概念 — 模板語法(Template Syntax)

簡介

在 Vue 3 中,模板語法是連結 UI 與資料的橋樑。開發者只需要在 .vue 檔的 <template> 區塊寫類似 HTML 的標記,即可讓畫面自動根據資料變化而更新。掌握模板語法不僅能快速構建介面,還能避免大量的 DOM 操作,讓程式碼更具可讀性與可維護性。

本篇文章以 Vue 3 為前提,說明最常用的模板指令、插值、條件與迴圈渲染等核心概念,並提供實作範例與最佳實踐,幫助你在實務專案中快速上手、減少錯誤。


核心概念

1. 資料插值(Interpolation)

最基本的模板語法是 雙大括號 {{ }},用來把 JavaScript 表達式的結果渲染到 HTML 中。

<template>
  <h1>歡迎,{{ user.name }}!</h1>
  <p>今天是 {{ new Date().toLocaleDateString() }}。</p>
</template>

<script setup>
import { ref } from 'vue'

const user = ref({ name: '小明' })
</script>
  • {{ }} 內只能放單行表達式,不允許使用語句(如 iffor)。
  • 只要 user.name 的值變動,對應的文字會即時更新。

2. 指令(Directives)

指令是以 v- 開頭的特殊屬性,提供 條件渲染、迴圈、事件綁定 等功能。最常見的有:

指令 功能說明 範例
v-bind / : 動態綁定 HTML 屬性 <img :src="imgUrl" alt="圖片">
v-on / @ 綁定事件監聽器 <button @click="increment">+</button>
v-if / v-else-if / v-else 條件渲染 <p v-if="isLogin">已登入</p>
v-show 顯示/隱藏(使用 CSS) <div v-show="visible">內容</div>
v-for 迭代陣列或物件 <li v-for="item in list" :key="item.id">{{ item.text }}</li>
v-model 雙向綁定表單元素 <input v-model="msg" />

2.1 v-bind 與縮寫 :

v-bind 可以把 JavaScript 表達式的值綁定到任意屬性上,常用於 動態 class、style、src 等。

<template>
  <button :class="{ active: isActive }" :style="{ color: btnColor }">
    點我
  </button>
</template>

<script setup>
import { ref } from 'vue'

const isActive = ref(true)
const btnColor = ref('white')
</script>

小技巧:若要一次綁定多個屬性,可使用物件語法 v-bind="{ href, target }"


2.2 事件綁定 v-on@

Vue 會自動把事件的 event 參數傳入,若不需要可以省略。

<template>
  <input @keyup.enter="submit" placeholder="按 Enter 送出" />
</template>

<script setup>
function submit(event) {
  console.log('送出內容:', event.target.value)
}
</script>

2.3 條件渲染 v-if / v-else-if / v-else

v-if 會在條件改變時銷毀或重新建立 DOM,適合較大或昂貴的區塊;v-show 只改變 display,適合頻繁切換的小區塊。

<template>
  <p v-if="status === 'loading'">載入中…</p>
  <p v-else-if="status === 'error'">發生錯誤!</p>
  <p v-else>資料已載入。</p>
</template>

<script setup>
import { ref } from 'vue'

const status = ref('loading') // loading / error / success
</script>

2.4 迭代渲染 v-for

v-for 必須提供唯一的 key,這對 Vue 的 diff 演算法至關重要。

<template>
  <ul>
    <li v-for="todo in todos" :key="todo.id">
      <input type="checkbox" v-model="todo.done" />
      <span :class="{ done: todo.done }">{{ todo.text }}</span>
    </li>
  </ul>
</template>

<script setup>
import { ref } from 'vue'

const todos = ref([
  { id: 1, text: '學習 Vue', done: false },
  { id: 2, text: '寫部落格', done: true },
])
</script>

<style scoped>
.done { text-decoration: line-through; }
</style>

2.5 雙向綁定 v-model

v-model 會自動把表單值與資料屬性同步,支援 修飾符.lazy.number.trim)以控制更新時機與類型。

<template>
  <input v-model.trim="username" placeholder="輸入使用者名稱" />
  <input type="number" v-model.number="age" placeholder="年齡" />
  <p>您好,{{ username }},您 {{ age }} 歲。</p>
</template>

<script setup>
import { ref } from 'vue'

const username = ref('')
const age = ref(null)
</script>

3. 動態組件與 v-slot(插槽)

在大型應用中,我們常需要 在父層傳遞 UI 結構,此時可以使用 <component :is="..."> 搭配 具名插槽

<template>
  <!-- 父層 -->
  <DynamicCard :is="currentCard">
    <template #header>
      <h2>{{ title }}</h2>
    </template>
    <template #default>
      <p>卡片內容由父層決定。</p>
    </template>
  </DynamicCard>
</template>

<script setup>
import { ref } from 'vue'
import DynamicCard from './DynamicCard.vue'

const currentCard = ref('InfoCard')
const title = ref('最新消息')
</script>
<!-- DynamicCard.vue -->
<template>
  <component :is="type" class="card">
    <slot name="header"></slot>
    <slot></slot>
  </component>
</template>

<script setup>
import { defineProps } from 'vue'

const props = defineProps({
  is: { type: String, required: true }
})
const type = props.is
</script>

重點v-slot 允許把 資料 從子組件傳回父層(slot-scope),在 Vue 3 中已改為 v-slot="{ data }" 的語法。


常見陷阱與最佳實踐

陷阱 說明 解決方式
忘記加 key v-for 沒有唯一鍵會導致渲染錯位或效能下降。 為每筆資料提供穩定且唯一的 id,盡量避免使用索引作為 key。
{{ }} 中使用語句 只能放表達式,語句會拋錯。 把複雜邏輯搬到 computedmethods 中,模板只保留簡單表達式。
過度使用 v-if 大量 v-if 會頻繁掛載/銷毀 DOM,影響效能。 若元素頻繁切換,改用 v-show;若條件只在初始化決定,仍使用 v-if
雙向綁定過度 v-model 直接修改資料,可能導致不可預期的副作用。 僅在表單輸入與 UI 同步時使用,其他情況使用單向綁定加事件處理。
插值過長 長度超過 2000+ 字元的插值會降低可讀性。 把大型文字或 HTML 片段抽離成子組件或使用 v-html(注意 XSS)。

最佳實踐

  1. 保持模板簡潔:所有業務邏輯放在 setup()computedstore 中,模板只負責渲染。
  2. 使用 script setup:減少樣板程式碼,提升可讀性。
  3. 分離樣式:使用 <style scoped> 或 CSS Modules,避免樣式洩漏。
  4. 預先定義類型:在 TypeScript 專案中,為 props、data、emit 定義介面,提升開發體驗。
  5. 善用 v-memo(Vue 3.3+):對不常變動的區塊使用 v-memo,減少不必要的重新渲染。

實際應用場景

  1. 表單驗證與即時回饋
    使用 v-model 兩端綁定表單欄位,配合 computed 判斷錯誤訊息,透過 v-if 即時顯示驗證結果。

  2. 動態列表與分頁
    v-for 搭配 key 渲染 API 回傳的商品清單,使用 v-show 切換「載入中」與「無資料」狀態,提升使用者體驗。

  3. 可重用卡片元件
    透過 <component :is="..."> 與具名插槽 v-slot,讓同一個卡片框架支援多種內容(圖表、文字、表格),降低重複程式碼。

  4. 條件式功能切換
    在權限管理系統中,以 v-if 控制不同角色的功能按鈕,確保 UI 與後端權限保持一致。

  5. 動畫與過渡
    結合 <transition>v-show 以及 CSS 動畫,實作彈出視窗、下拉選單等互動效果。


總結

模板語法是 Vue 3 最核心的特性之一,簡潔的插值、強大的指令以及靈活的插槽 讓開發者能以宣告式的方式快速構建 UI。掌握以下要點,就能在實務專案裡寫出 可讀、可維護且效能良好 的程式碼:

  • 使用 {{ }} 只放簡單表達式,複雜邏輯移至 computedmethods
  • v-bindv-on 的縮寫 :@ 能大幅減少樣板。
  • 針對不同需求選擇 v-if(掛載/銷毀)或 v-show(CSS 隱藏)。
  • v-for 必須配合唯一 key,避免渲染錯位。
  • v-model 方便表單雙向綁定,但要注意過度使用的副作用。
  • 動態組件與插槽提供高度可組合的 UI 結構,適合大型專案的模組化開發。

只要遵循以上最佳實踐,你就能在 Vue 3 的模板語法世界裡,快速開發出功能完整且具備良好使用者體驗的 Web 應用。祝你寫程式開心,專案順利!