如果有任何問題或建議,歡迎隨時聯繫我:
大家好!昨天我們一起探索了 Vue 的互動核心 v-bind 和 v-on,學會了如何讓資料與畫面同步、如何傾聽使用者的操作。現在,我們的應用程式已經有了「互動」的能力。
今天,我們要更進一步,學習如何控制畫面的「結構」。你會學到如何根據不同的條件,決定一個元素是否應該出現在畫面上 (條件渲染),以及如何根據一組資料,動態地產生一整個列表的元素 (列表渲染)。
這兩個強大的指令——v-if 和 v-for——是所有動態介面的基石。掌握它們,你就能從只能做「靜態頁面」的開發者,蛻變為能打造「動態應用」的工程師。
在開發中,我們經常需要根據某個狀態來決定是否顯示某個區塊。例如:
這就是 v-if 的主場。
v-if, v-else, v-else-if:非黑即白,或多重選擇v-if 會根據一個布林值的表達式來決定是否渲染一個元素。如果表達式為 true,元素就會被建立並插入 DOM;如果為 false,元素就會被銷毀。
<script setup>
import { ref } from 'vue';
const isLoggedIn = ref(false);
</script>
<template>
<button @click="isLoggedIn = !isLoggedIn">
{{ isLoggedIn ? '登出' : '登入' }}
</button>
<div v-if="isLoggedIn">
<p>歡迎回來,VIP 使用者!</p>
</div>
<div v-else>
<p>請先登入以查看更多內容。</p>
</div>
</template>
在這個例子中,
div的顯示與否完全由isLoggedIn這個 ref 變數控制。v-else則提供了一個「備案」,它必須緊跟在v-if或v-else-if的元素後面。
v-if vs v-show:真正的銷毀 vs 單純的隱藏Vue 提供了另一個指令 v-show,它也能根據條件控制元素的可見性。但它和 v-if 有個關鍵的區別:
v-if 是 「真正的」條件渲染。如果條件為假,對應的元素會被完全從 DOM 中移除。當條件變為真時,才會重新建立、編譯、並掛載元素。v-show 則是 基於 CSS 的切換。無論條件是真是假,元素始終會被渲染在 DOM 中。v-show 只是簡單地切換元素的 display: none; CSS 屬性。該用哪個?
v-if 有更高的「切換開銷」,因為它涉及 DOM 的新增和刪除。v-show 有更高的「初始渲染開銷」,因為它一開始就需要把元素渲染出來。v-show 效能會更好。如果條件 很少改變(例如,使用者登入狀態),或者你希望確保在條件為假時,元素內的組件完全不會被渲染或執行,那麼 v-if 是更合適的選擇。v-for 讓我們可以基於一個陣列來渲染一個列表。它的語法是 item in items,非常直觀。
:key 的重要性假設我們有一個待辦事項清單:
<script setup>
import { ref } from 'vue';
const todos = ref([
{ id: 1, text: '學習 Vue' },
{ id: 2, text: '撰寫鐵人賽文章' },
{ id: 3, text: '休息一下' }
]);
</script>
<template>
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
</li>
</ul>
</template>
v-for會遍歷todos陣列,為每個todo物件渲染一個<li>元素。
注意到了嗎?那個 :key 是什麼?
key 是 Vue 用來識別 VDOM 中每個節點的「身份證」。當你的資料列表更新時(例如新增、刪除、或重新排序),Vue 會使用 key 來匹配新舊節點,以決定如何最高效地更新 DOM。
key? 如果沒有 key,Vue 會採用一種「就地更新」的策略,它會盡量複用相同位置的元素,只更新其內容。這在某些情況下會導致非預期的行為,尤其是在列表包含表單輸入或子組件時。index 當 key? v-for 也提供 (item, index) in items 的語法來獲取索引。但使用 index 作為 key 是非常危險的。想像一下,你刪除了列表中的第一項,原本 index 為 1 的項目現在變成了 index 0,index 為 2 的變成了 1... 所有 key 都亂掉了!這會讓 Vue 感到困惑,可能導致錯誤的 DOM 更新,效能也更差。最佳實踐:永遠為 v-for 綁定一個 唯一且穩定 的 key,通常是來自你資料的 id。
v-if 與 v-for 一起用?請三思!一個常見的錯誤是把 v-if 和 v-for 放在同一個元素上。
<!-- ❌ 不推薦的寫法 -->
<li v-for="user in users" v-if="user.isActive" :key="user.id">
{{ user.name }}
</li>
為什麼不好? 因為在 Vue 中,v-for 的優先級比 v-if 更高。這意味著,Vue 會先遍歷 所有 的 users,然後在每次迭代中再用 v-if 進行判斷。如果你的 users 陣列有一千個項目,但只有十個是 isActive 的,你依然會遍歷一千次!
正確的做法:
使用 computed 屬性(推薦):先在 <script> 中把列表過濾好,再用 v-for 渲染過濾後的結果。這讓模板保持乾淨,且效能更好。
const activeUsers = computed(() => {
return users.value.filter(user => user.isActive);
});
<!-- ✅ 推薦的寫法 -->
<li v-for="user in activeUsers" :key="user.id">
{{ user.name }}
</li>
使用 <template> 包裝:如果你不想用 computed,可以將 v-if 移到外層的 <template> 標籤上。
<template v-for="user in users" :key="user.id">
<li v-if="user.isActive">
{{ user.name }}
</li>
</template>
思考一:v-if vs v-show 的抉擇
假設你在設計一個有「編輯模式」和「預覽模式」的個人資料頁面。使用者可以點擊一個按鈕來回切換這兩種模式。你會選擇用 v-if 還是 v-show 來控制這兩個模式的顯示與隱藏?為什麼?
思考二:key 的威力
想像一個可以讓使用者自由拖曳排序的任務列表。如果這個列表的 v-for 是用 index 作為 key,當使用者拖曳交換了兩個任務的位置後,你覺得 Vue 的更新過程會發生什麼事?如果改用任務的 id 作為 key,又會如何不同?
今天我們學會了 Vue 中控制 DOM 結構的兩大指令:v-if 和 v-for。它們讓我們能夠根據應用程式的狀態,動態地新增、移除或渲染元素列表。
掌握它們的用法與之間的差異,特別是 v-if 與 v-show 的選擇,以及為 v-for 提供穩定 key 的重要性,是寫出高效能、可預測 Vue 應用的關鍵。
本日關鍵字回顧
v-if, v-else, v-else-if: 條件渲染,會實際新增或銷毀 DOM 節點。v-show: 條件顯示,透過 CSS display 屬性控制可見性。v-for: 列表渲染,用於遍歷陣列並產生元素。:key: 節點的唯一身份標識,對高效的 DOM 更新至關重要。v-for 與 v-if 的優先級: v-for 高於 v-if,避免在同一元素上同時使用。明天,我們將進入 Vue 最迷人的核心概念之一:組件化。我們將學習如何把介面拆分成一個個可複用的積木,敬請期待!