本文 AI 產出,尚未審核

Vue3 教學:模板語法 – Mustache ({{ variable }})

簡介

在 Vue3 中,模板 (Template) 是與資料互動的第一層介面。大多數新手在看到 Vue 組件的 .vue 檔時,第一眼會注意到 {{ }} 這對大括號——也就是 Mustache 語法。它看似簡單,卻是 Vue 資料綁定 (Data Binding) 的核心入口,負責把 JavaScript 中的資料「渲染」到 HTML,讓畫面隨資料變化而即時更新。

掌握 Mustache 語法不只讓你能快速顯示文字、數字或計算結果,更是深入了解 響應式系統生命週期組件溝通 的基礎。若能正確運用,開發者可以在不寫任何 DOM 操作程式碼的情況下,建立互動且易於維護的 UI。

本篇文章將從 概念實作範例常見陷阱最佳實踐 以及 實務應用 四個面向,完整說明 Mustache 語法在 Vue3 中的使用方式,幫助初學者快速上手,也讓中級開發者進一步優化寫法。


核心概念

1. Mustache 為何叫「插值」

Mustache 本質上是一種 文字插值 (Interpolation),語法為 {{ expression }},其中 expression 必須是一個 單一的 JavaScript 表達式,且 只能返回字串、數字、布林或可被 Vue 自動轉換的值。Vue 會在組件建立時解析這段表達式,將結果插入對應的 DOM 節點;之後若相關的 reactive 資料發生變化,Vue 會自動重新渲染。

⚡ 重點:Mustache 不支援 陳述式 (如 iffor)、函式宣告或多行程式碼;若需要複雜邏輯,請改用 computedmethodsv‑if / v‑for

2. 何時使用 Mustache

場景 建議使用 替代方案
顯示純文字、數字、布林值 ✅ Mustache
需要 HTML 標籤或屬性動態化 ❌ Mustache → v-htmlv-bind
多條件或迴圈渲染 ❌ Mustache → v-ifv-for
需要執行方法或計算結果 ✅ 在 computed 中先處理,再用 Mustache 顯示

3. 基本語法規則

  1. 單向綁定{{ data }} 只會把資料寫入 DOM,不會把使用者輸入寫回資料。
  2. 自動 HTML 逃脫:插值的內容會自動轉義,防止 XSS 攻擊。若要輸出原始 HTML,需改用 v-html
  3. 支援過濾器 (Vue 3 已棄用):舊版 Vue2 常見 {{ msg | capitalize }},在 Vue3 中改用 computedmethods

程式碼範例

以下範例均以 單檔組件 (Single File Component) 為基礎,使用 <script setup> 語法,讓程式碼更簡潔。

範例 1:顯示基本資料

<template>
  <h2>使用者資訊</h2>
  <!-- Mustache 直接插入文字 -->
  <p>姓名:{{ name }}</p>
  <p>年齡:{{ age }}</p>
  <p>已驗證:{{ isVerified ? '是' : '否' }}</p>
</template>

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

const name = ref('陳小明')
const age = ref(28)
const isVerified = ref(true)
</script>

說明{{ isVerified ? '是' : '否' }} 為單行三元運算子,仍屬於「單一表達式」的範疇,符合 Mustache 的限制。

範例 2:使用 computed 處理衍生資料

<template>
  <h3>商品資訊</h3>
  <p>原價:${{ price }}</p>
  <p>折扣後價格:${{ discountedPrice }}</p>
  <p>顯示訊息:{{ priceMessage }}</p>
</template>

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

const price = ref(1200)
const discount = ref(0.15)

// 計算折扣後的價格
const discountedPrice = computed(() => {
  return Math.round(price.value * (1 - discount.value))
})

// 產生需要顯示的訊息,使用 computed 讓 Mustache 只負責插值
const priceMessage = computed(() => {
  return discountedPrice.value < 1000
    ? '價格已低於 1000 元,快下單!'
    : '仍在原價區間。'
})
</script>

說明:將較複雜的邏輯放入 computed,保持 Mustache 只負責「顯示」而不做運算,提升可讀性與效能。

範例 3:多層物件與陣列的插值

<template>
  <h3>待辦清單</h3>
  <ul>
    <!-- 直接插入陣列元素的屬性 -->
    <li v-for="(item, idx) in todoList" :key="idx">
      {{ idx + 1 }}. {{ item.title }} - {{ item.done ? '完成' : '未完成' }}
    </li>
  </ul>
</template>

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

const todoList = reactive([
  { title: '寫教學文章', done: true },
  { title: '練習 Vue3', done: false },
  { title: '閱讀技術文件', done: false }
])
</script>

說明v-for 本身不是 Mustache,但在迭代時仍可在 {{ }} 中使用 陣列索引物件屬性,只要保持為單行表達式即可。

範例 4:字串拼接與模板字面量

<template>
  <p>歡迎訊息:{{ welcomeMessage }}</p>
</template>

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

const user = ref({ name: '林志玲', role: '管理員' })

// 使用模板字面量組合字串
const welcomeMessage = computed(() => {
  return `嗨 ${user.value.name},您是 ${user.value.role}。`
})
</script>

說明:即使在 computed 中使用 ES6 的模板字面量,最後仍以單一值回傳給 Mustache,符合語法規範。

範例 5:自訂全域過濾器(Vue3 推薦做法)

<template>
  <p>大寫姓名:{{ upperName }}</p>
</template>

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

// 直接在 computed 中完成過濾功能
const name = ref('王大明')
const upperName = computed(() => name.value.toUpperCase())
</script>

說明:Vue3 已移除過濾器(filter)功能,建議以 computedmethod 取代,以保持程式碼一致性與型別安全。


常見陷阱與最佳實踐

陷阱 可能的結果 解決方法
插入 HTML 標籤 文字被自動轉義,顯示 <b>文字</b> 而非粗體 使用 v-html(僅限可信內容)或在 computed 中產生安全的 HTML
在 Mustache 內寫多行程式 解析錯誤、編譯失敗 把程式碼抽到 computedmethods,只在 Mustache 中放單行表達式
使用非 reactive 變數 資料變更不會觸發重新渲染 使用 refreactivecomputed,或在 setup 中返回普通變數給模板
在迴圈中直接改變陣列 可能導致渲染錯位或效能下降 使用 v-for 搭配 :key,並在資料層面使用 pushsplice 等 Vue 支援的變更方式
過度使用 Mustache 進行條件判斷 可讀性差、維護困難 把條件邏輯搬到 computed,或改用 v-if / v-show 控制顯示

最佳實踐

  1. 保持 Mustache 為「純展示」:所有計算、條件判斷、字串處理均放在 computedmethods 中。
  2. 使用 ref / reactive:確保資料具備 響應式,否則插值不會自動更新。
  3. 加入 :key:在 v-for 搭配 Mustache 時,務必提供唯一鍵值,避免列表重排導致 UI 異常。
  4. 避免 XSS:除非確信內容安全,千萬不要在 Mustache 中直接插入使用者輸入的 HTML。
  5. 統一風格:在團隊內部規範「所有 Mustache 表達式僅允許單行、無副作用」的寫法,提升代碼一致性。

實際應用場景

1. 儀表板 (Dashboard) 中的即時指標

在金融或監控系統的儀表板,常需要即時顯示 數字、百分比、狀態文字。透過 Mustache 搭配 refcomputed,可以在資料變動時自動刷新 UI,無需手動操作 DOM。

<template>
  <div class="stats">
    <p>CPU 使用率:{{ cpuUsage }}%</p>
    <p>記憶體剩餘:{{ freeMemory }} MB</p>
    <p>系統狀態:{{ systemStatus }}</p>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'

const cpuUsage = ref(0)
const freeMemory = ref(0)

const systemStatus = computed(() => {
  if (cpuUsage.value > 80) return '高負載'
  if (cpuUsage.value > 50) return '正常'
  return '閒置'
})

// 模擬每秒更新一次的資料來源
onMounted(() => {
  setInterval(() => {
    cpuUsage.value = Math.round(Math.random() * 100)
    freeMemory.value = Math.round(8000 + Math.random() * 2000)
  }, 1000)
})
</script>

2. 多語言 (i18n) 文字插值

使用 vue-i18n 時,常會在模板中直接插入翻譯字串。Mustache 能簡潔呈現 動態佔位符

<template>
  <p>{{ $t('welcome', { name: userName }) }}</p>
</template>

<script setup>
import { ref } from 'vue'
const userName = ref('張惠妹')
</script>

$t 返回的字串已經完成插值,Mustache 僅負責顯示。

3. 表單回饋訊息

在表單驗證成功或失敗時,常需要顯示即時的提示文字。利用 ref 追蹤錯誤訊息,再以 Mustache 渲染。

<template>
  <form @submit.prevent="handleSubmit">
    <input v-model="email" type="email" placeholder="請輸入 Email" />
    <p class="error">{{ emailError }}</p>
    <button type="submit">送出</button>
  </form>
</template>

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

const email = ref('')
const emailError = ref('')

function handleSubmit() {
  if (!email.value.includes('@')) {
    emailError.value = '請輸入有效的 Email 地址!'
  } else {
    emailError.value = ''
    // 送出資料...
  }
}
</script>

總結

Mustache ({{ variable }}) 是 Vue3 中最直觀、最常見的 文字插值 方式。它的核心概念是 單向、響應式、HTML 逃脫,讓開發者只需關注資料本身,而不必擔心 DOM 更新的細節。

  • 保持單行、純展示:將所有邏輯搬到 computedmethods,讓模板保持乾淨。
  • 使用 ref / reactive:確保資料具備響應式,才能驅動 Mustache 自動重繪。
  • 注意安全:除非內容可信,切勿使用 Mustache 輸出未過濾的 HTML,以免產生 XSS。
  • 遵循最佳實踐:結合 v-ifv-forv-bind 等指令,讓 UI 更具彈性與可維護性。

透過本文的概念解說與多個實務範例,你應該已經能在 Vue3 專案中自如使用 Mustache,從簡單的文字顯示到即時儀表板、國際化與表單回饋,都能快速完成。未來在面對更複雜的 UI 需求時,只要遵循「資料驅動、模板純粹」的原則,Vue3 的模板語法將持續為你提供高效、可讀且易於維護的開發體驗。祝你寫程式愉快! 🚀