Vue 模板語法
Vue 使用基於 HTML 的模板語法,讓你可以聲明式地將元件實例的資料綁定到渲染的 DOM 上。所有 Vue 模板都是合法的 HTML,可以被符合規範的瀏覽器和 HTML 解析器解析。
文字插值(Text Interpolation)
最基本的資料綁定形式是使用雙大括號(Mustache 語法)進行文字插值:
<script setup>
import { ref } from 'vue'
const message = ref('Hello, Vue!')
</script>
<template>
<p>訊息:{{ message }}</p>
</template>
{{ message }} 會被替換為 message 的值,並且當 message 改變時,畫面也會自動更新。
在插值中使用 JavaScript 表達式
雙大括號中可以使用任何有效的 JavaScript 表達式:
<script setup>
import { ref } from 'vue'
const number = ref(10)
const ok = ref(true)
const message = ref('hello')
const id = ref('item-1')
</script>
<template>
<!-- 數學運算 -->
<p>{{ number + 1 }}</p>
<!-- 三元運算子 -->
<p>{{ ok ? 'YES' : 'NO' }}</p>
<!-- 呼叫方法 -->
<p>{{ message.split('').reverse().join('') }}</p>
<!-- 模板字串 -->
<p>{{ `ID: ${id}` }}</p>
</template>
{{ if (ok) { return message } }} 是無效的,因為 if 是陳述式。插值的限制
每個綁定只能包含單一表達式,以下是不合法的:
<!-- 這是陳述式,不是表達式 -->
{{ var a = 1 }}
<!-- 流程控制也不行,請使用三元運算子 -->
{{ if (ok) { return message } }}
原始 HTML(Raw HTML)
雙大括號會將資料解析為純文字,如果你想輸出真正的 HTML,需要使用 v-html 指令:
<script setup>
import { ref } from 'vue'
const rawHtml = ref('<span style="color: red">這是紅色文字</span>')
</script>
<template>
<!-- 顯示為純文字 -->
<p>使用雙括號:{{ rawHtml }}</p>
<!-- 解析為 HTML -->
<p>使用 v-html:<span v-html="rawHtml"></span></p>
</template>
輸出結果:
- 使用雙括號:
<span style="color: red">這是紅色文字</span> - 使用 v-html:這是紅色文字
v-text 指令
v-text 用於更新元素的文字內容,效果等同於雙大括號,但會覆蓋元素內的所有內容:
<script setup>
import { ref } from 'vue'
const message = ref('Hello')
</script>
<template>
<!-- 以下兩種寫法效果相同 -->
<span v-text="message"></span>
<span>{{ message }}</span>
</template>
大多數情況下,使用 {{ }} 會更直覺,v-text 較少使用。
屬性綁定(Attribute Bindings)
雙大括號不能用在 HTML 屬性中,要綁定屬性需要使用 v-bind 指令:
<script setup>
import { ref } from 'vue'
const dynamicId = ref('my-id')
const imageUrl = ref('https://vuejs.org/images/logo.png')
</script>
<template>
<div v-bind:id="dynamicId">這個 div 的 id 是動態的</div>
<img v-bind:src="imageUrl" alt="Vue Logo">
</template>
簡寫語法
因為 v-bind 非常常用,Vue 提供了簡寫語法,直接使用 : 即可:
<template>
<!-- 完整語法 -->
<div v-bind:id="dynamicId"></div>
<!-- 簡寫語法(推薦) -->
<div :id="dynamicId"></div>
<img :src="imageUrl" alt="Vue Logo">
</template>
同名簡寫(Vue 3.4+)
從 Vue 3.4 開始,如果屬性名稱和綁定的變數名稱相同,可以進一步簡化:
<script setup>
import { ref } from 'vue'
const id = ref('my-id')
</script>
<template>
<!-- 完整寫法 -->
<div :id="id"></div>
<!-- 同名簡寫(Vue 3.4+) -->
<div :id></div>
</template>
布林屬性(Boolean Attributes)
對於布林屬性(如 disabled、readonly),Vue 會根據值的真假來決定是否渲染該屬性:
<script setup>
import { ref } from 'vue'
const isButtonDisabled = ref(true)
</script>
<template>
<button :disabled="isButtonDisabled">按鈕</button>
</template>
- 當
isButtonDisabled為true或空字串"":渲染為<button disabled> - 當
isButtonDisabled為false、null或undefined:disabled屬性不會被渲染
動態綁定多個屬性
如果你有一個物件包含多個屬性,可以使用不帶參數的 v-bind 一次綁定所有屬性:
<script setup>
import { reactive } from 'vue'
const inputAttrs = reactive({
id: 'username',
type: 'text',
placeholder: '請輸入使用者名稱'
})
</script>
<template>
<!-- 一次綁定多個屬性 -->
<input v-bind="inputAttrs">
<!-- 等同於 -->
<input :id="inputAttrs.id" :type="inputAttrs.type" :placeholder="inputAttrs.placeholder">
</template>
動態參數(Dynamic Arguments)
你也可以在指令的參數中使用 JavaScript 表達式,用方括號包起來:
<script setup>
import { ref } from 'vue'
const attributeName = ref('href')
const url = ref('https://vuejs.org')
const eventName = ref('click')
const handleEvent = () => {
console.log('事件觸發了!')
}
</script>
<template>
<!-- 動態屬性名稱 -->
<a :[attributeName]="url">Vue 官網</a>
<!-- 動態事件名稱 -->
<button @[eventName]="handleEvent">點我</button>
</template>
動態參數的限制
- 值的限制:動態參數應該是字串,或者是
null(null會移除該綁定) - 語法限制:避免使用空格和引號等字元,因為 HTML 屬性名稱不允許這些字元
<!-- 這會觸發編譯警告 -->
<a :['foo' + bar]="value"> ... </a>
如果需要複雜的動態參數,建議使用 computed 屬性。
Class 與 Style 綁定
Vue 對 class 和 style 的綁定做了特別加強,表達式的值除了字串外,還可以是物件或陣列。
綁定 Class - 物件語法
<script setup>
import { ref } from 'vue'
const isActive = ref(true)
const hasError = ref(false)
</script>
<template>
<!-- 物件語法 -->
<div :class="{ active: isActive, 'text-danger': hasError }">
Class 綁定範例
</div>
</template>
<style>
.active { font-weight: bold; }
.text-danger { color: red; }
</style>
渲染結果:<div class="active">Class 綁定範例</div>
綁定 Class - 陣列語法
<script setup>
import { ref } from 'vue'
const activeClass = ref('active')
const errorClass = ref('text-danger')
</script>
<template>
<!-- 陣列語法 -->
<div :class="[activeClass, errorClass]">
Class 綁定範例
</div>
</template>
渲染結果:<div class="active text-danger">Class 綁定範例</div>
綁定 Style - 物件語法
<script setup>
import { ref } from 'vue'
const activeColor = ref('red')
const fontSize = ref(30)
</script>
<template>
<!-- 物件語法 - CSS 屬性名稱使用 camelCase 或 kebab-case -->
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }">
Style 綁定範例
</div>
<!-- 也可以用 kebab-case,但需要加引號 -->
<div :style="{ color: activeColor, 'font-size': fontSize + 'px' }">
Style 綁定範例
</div>
</template>
綁定 Style - 陣列語法
<script setup>
import { reactive } from 'vue'
const baseStyles = reactive({
color: 'blue',
fontSize: '16px'
})
const overridingStyles = reactive({
fontWeight: 'bold'
})
</script>
<template>
<!-- 合併多個樣式物件 -->
<div :style="[baseStyles, overridingStyles]">
Style 綁定範例
</div>
</template>
指令(Directives)
指令是帶有 v- 前綴的特殊屬性。指令的職責是當表達式的值改變時,將相應的效果套用到 DOM 上。
<p v-if="seen">現在你看到我了</p>
這裡 v-if 指令會根據 seen 的真假值來插入或移除 <p> 元素。
指令語法結構
v-指令名稱:參數.修飾符="值"
以 v-on:submit.prevent="onSubmit" 為例:
- 指令名稱:
on - 參數:
submit(監聽的事件名稱) - 修飾符:
prevent(呼叫event.preventDefault()) - 值:
onSubmit(要執行的方法)
常見指令一覽
| 指令 | 說明 | 簡寫 |
|---|---|---|
v-bind | 動態綁定屬性 | : |
v-on | 監聯事件 | @ |
v-model | 雙向資料綁定 | 無 |
v-if | 條件渲染 | 無 |
v-show | 條件顯示/隱藏 | 無 |
v-for | 列表渲染 | 無 |
v-slot | 插槽 | # |
更多指令的詳細用法請參考 Vue 指令。