如果有任何問題或建議,歡迎隨時聯繫我:
昨天我們聊了 Vue 3 的核心演進,知道了它背後那套讓我們開發更順暢的「組合式 API」與效能優化的黑魔法。但光說不練,總覺得有點空虛。今天,我們就來動手玩點真的,深入 Vue 世界最基本、也最重要的互動核心:資料綁定 (v-bind) 與 事件處理 (v-on)。
這兩個指令,可以說是 Vue 的任督二脈。一旦打通,你的網頁就能從「靜態的展示品」變成「能與使用者互動的應用程式」。準備好讓你的網頁活起來了嗎?
想像一下,你的網頁是一具提線木偶,而你的資料(在 Vue 的 <script setup> 裡定義的變數)就是控制木偶的線。資料綁定 就是把這些線(資料)跟木偶的特定部位(HTML 元素)綁在一起的過程。
v-bind:單向的資料流v-bind 就像一條單行道,資料只能從 <script> 流向 template (HTML)。當你的資料改變時,畫面會自動更新,但反過來不行。
最常見的用途就是綁定 HTML 元素的屬性 (Attribute),例如圖片的 src、連結的 href,或是元素的 class 和 style。
語法:v-bind:屬性名="資料變數",不過在實務上,大家更愛用它的縮寫:一個簡單的冒號 :屬性名。
舉個例子: 讓我們來綁定一張圖片的 URL 和一個 class。
<script setup>
import { ref, computed } from 'vue';
const vueLogoUrl = ref('https://vuejs.org/images/logo.png');
const isImportant = ref(true);
// 我們也可以綁定一個 computed property
const textClasses = computed(() => ({
'important': isImportant.value,
'normal-text': !isImportant.value,
}));
</script>
<template>
<!-- 基本綁定 -->
<img :src="vueLogoUrl" alt="Vue Logo">
<!-- 綁定 class -->
<p :class="textClasses">這段文字會根據 isImportant 的值改變樣式。</p>
<!-- 切換按鈕 -->
<button @click="isImportant = !isImportant">
切換重要性
</button>
</template>
<style>
.important {
color: red;
font-weight: bold;
}
.normal-text {
color: black;
}
</style>
在這個例子中,圖片的
src被vueLogoUrl這個 ref 變數控制。p標籤的class則由textClasses這個計算屬性動態決定。當你點擊按鈕,isImportant的值改變,textClasses會重新計算,p標籤的樣式也跟著更新。這就是單向綁定的威力!
你可能會好奇,<img :src="vueLogoUrl"> 這段看起來像 HTML 的程式碼,瀏覽器又看不懂,Vue 到底是怎麼讓它動起來的?
這就是 Vue 編譯器 (Compiler) 的功勞。在你執行 npm run dev 或 npm run build 時,Vue 會把你的 .vue 檔案模板 (template) 進行編譯,轉換成瀏覽器看得懂的 JavaScript 渲染函式 (Render Function)。
所以,<img :src="vueLogoUrl"> 會被轉換成類似這樣的程式碼:
import { h } from 'vue'
// ... 渲染函式內部 ...
return h('img', { src: vueLogoUrl.value, alt: 'Vue Logo' })
h() 函式會建立一個 虛擬 DOM (Virtual DOM) 節點。當 vueLogoUrl 的值改變時,Vue 的響應式系統會偵測到變化,並重新執行渲染函式,產生新的虛擬 DOM。接著,Vue 會比較新舊虛擬 DOM 的差異,並只更新真實 DOM 中真正改變的部分(也就是 src 屬性)。
這個過程非常高效,也是 Vue 效能優異的核心祕密之一。
computed vs template 內聯判斷當綁定的值需要一些邏輯判斷時,你有兩種主要選擇:
<p :class="isImportant ? 'important' : 'normal-text'">
這段文字很重要。
</p>
<script> 的 computed 函式中。
<!-- :class="textClasses" -->
(如我們上方的 textClasses 範例)應該選哪個? -> 強烈推薦 computed!
雖然內聯表達式對於極度簡單的邏輯來說很方便,但只要你的邏輯稍微複雜一點,computed 就會是更好的選擇。理由如下:
computed 可以讓你輕鬆複用,而不用複製貼上一堆表達式。computed 是基於其響應式依賴進行快取的。只有當依賴的 ref (例如 isImportant) 發生變化時,它才會重新計算。而內聯表達式或 method 則是在每次元件重新渲染時都會重新執行,效能較差。<script> 中的邏輯遠比在 <template> 中的邏輯更容易進行單元測試。結論:當你的綁定需要任何形式的邏輯運算時,優先考慮使用 computed。這是一個能顯著提升你程式碼品質的好習慣。
v-model:雙向的溝通橋樑如果 v-bind 是單行道,那 v-model 就是一條雙向高速公路。它通常用在表單元素上,像是 <input>, <textarea>, <select>。
它同時做了兩件事:
v-bind 把資料綁定到輸入框的 value。v-on 監聽輸入框的 input 事件,並在事件觸發時更新資料。簡單來說:資料變,輸入框跟著變;輸入框變,資料也跟著變。
舉個例子: 一個簡單的即時回饋輸入框。
<script setup>
import { ref } from 'vue';
const message = ref('');
</script>
<template>
<input v-model="message" placeholder="隨便打點什麼...">
<p>你輸入的是:{{ message }}</p>
</template>
試著在輸入框裡打字,你會發現底下的文字會即時更新。這就是
v-model的魔力,它讓處理表單資料變得無比輕鬆。
如果資料綁定是讓畫面動起來,那事件處理就是讓使用者「參與」進來。當使用者點擊按鈕、滑動頁面、或是在鍵盤上敲敲打打時,我們需要一個機制來「聽到」這些動作,並做出回應。這個機制就是 v-on。
v-on:你的事件監聽器v-on 用來監聽 DOM 事件,並在事件觸發時執行指定的 JavaScript 程式碼。
語法:v-on:事件名="函式",同樣地,它也有個更受歡迎的縮寫:@事件名。
舉個例子: 一個簡單的計數器。
<script setup>
import { ref } from 'vue';
const count = ref(0);
function increment() {
count.value++;
}
function decrement() {
count.value--;
}
</script>
<template>
<p>目前的計數:{{ count }}</p>
<!-- 綁定一個已定義的函式 -->
<button @click="increment">增加</button>
<!-- 也可以直接寫簡單的表達式 -->
<button @click="decrement">減少</button>
</template>
這裡,我們用
@click分別在兩個按鈕上監聽了點擊事件。點擊時,它們會分別呼叫increment函式或執行count.value--這個表達式。
有時候我們需要對事件做一些額外的處理,例如「阻止預設行為」(像 a 標籤的跳轉)或「停止事件冒泡」。在傳統 JS 中,我們得手動呼叫 event.preventDefault() 或 event.stopPropagation()。
Vue 提供了一系列好用的事件修飾符,讓我們可以優雅地處理這些情況。
.prevent:阻止預設行為。.stop:停止事件冒泡。.once:事件只觸發一次。.self:只有當事件是從這個元素本身觸發時才觸發。.capture:使用事件捕獲模式。舉例: 阻止表單提交後重新整理頁面。
<form @submit.prevent="onSubmit">
<button type="submit">提交</button>
</form>
加上
.prevent修飾符後,點擊提交按鈕時,表單將不會觸發預設的頁面重整行為,而是只會執行我們的onSubmit函式。是不是乾淨俐落多了?
思考一:v-model 的雙面性
我們知道 v-model 提供了方便的「雙向綁定」。但它其實是 :value 綁定和 @input 事件監聽的語法糖。請試著思考:如果今天沒有 v-model,你該如何只用 :value 和 @input 來實現一個完全相同功能的輸入框?這有助於你更深刻地理解資料流。
思考二:邏輯應該放哪裡?
假設要做一個「文字反轉器」:一個輸入框,下方即時顯示反轉後的文字。你會如何實現「文字反轉」這個邏輯?
<p>{{ text.split('').reverse().join('') }}</p>
computed
這兩種方法都能達成目的,但哪一種的可讀性、效能和可維護性更好?為什麼?(提示:回想一下我們前面關於 computed 的討論!)
今天我們掌握了 Vue 中最核心的兩個互動工具:v-bind 和 v-on。v-bind(與它的雙向版本 v-model)負責讓我們的資料與畫面同步,而 v-on 則負責傾聽使用者的操作並做出反應。
這兩者結合起來,就構成了 Vue 響應式系統的基礎。無論多複雜的應用,其底層的互動邏輯都離不開這兩位好朋友。
本日關鍵字回顧
v-bind: 單向資料綁定,縮寫是 :。v-model: 雙向資料綁定,主要用於表單。v-on: 事件監聽,縮寫是 @。Event Modifiers: 事件修飾符,如 .prevent 和 .stop,讓事件處理更簡潔。明天,我們將繼續探索 Vue 的模板語法,學習如何根據條件顯示或隱藏元素 (v-if),以及如何渲染一個列表 (v-for)。敬請期待!