今天我們來聊聊 Vue 里兩位“重量級”選手——v-if 和 v-for。
你是不是也曾在同一個(gè)標(biāo)簽上同時(shí)寫過這兩個(gè)指令??? 結(jié)果發(fā)現(xiàn)頁面渲染出來的效果跟你預(yù)想的不太一樣?或者在 Vue 2 和 Vue 3 之間反復(fù)橫跳,被優(yōu)先級搞暈了頭?
別慌!這篇筆記不僅帶你搞定基礎(chǔ)用法,還要深扒它們的優(yōu)先級戰(zhàn)爭和性能內(nèi)幕,讓你徹底吃透這兩個(gè)指令!??
??? v-if:條件渲染的“守門員”
v-if 的作用很簡單:根據(jù)表達(dá)式的真假,來決定元素是“存在”還是“消失”。
- 真正的條件渲染:當(dāng)條件為 false 時(shí),元素壓根不會(huì)出現(xiàn)在 DOM 樹里,就像從來沒寫過一樣。
- 生命周期:因?yàn)樵乇讳N毀了,所以相關(guān)的組件生命周期鉤子(如 mounted)也會(huì)隨之觸發(fā)。
常用搭檔
- v-else-if:相當(dāng)于 else if。
- v-else:相當(dāng)于 else。
<div v-if="type === 'A'">
我是 A 類型
</div>
<div v-else-if="type === 'B'">
我是 B 類型
</div>
<div v-else>
我是默認(rèn)類型
</div>
?? 性能小貼士
v-if 是惰性的。如果初始條件是 false,Vue 啥都不干。只有當(dāng)條件第一次變成 true 時(shí),它才開始渲染。所以,它適合那些不經(jīng)常變化的條件。
??? v-show:CSS 的“障眼法”
雖然你問的是 v-if,但不得不提它的“雙胞胎兄弟” v-show。
- 區(qū)別:v-show 不管條件真假,元素永遠(yuǎn)都在 DOM 里。它只是簡單地切換 CSS 的 display 屬性(none 或 block)。
- 場景:如果你需要非常頻繁地切換顯示狀態(tài)(比如側(cè)邊欄折疊、Tab 切換),用 v-show 性能更好,因?yàn)樗恍枰磸?fù)銷毀和重建 DOM。
?? v-for:列表渲染的“復(fù)印機(jī)”
v-for 用來循環(huán)渲染列表。它不僅能遍歷數(shù)組,還能遍歷對象、Map,甚至是一個(gè)數(shù)字(用來循環(huán)次數(shù))。
基本語法
<!-- 遍歷數(shù)組 -->
<li v-for="(item, index) in items" :key="item.id">
{{ index }} - {{ item.name }}
</li>
<!-- 遍歷對象 -->
<div v-for="(value, key, index) in myObject">
{{ key }}: {{ value }}
</div>
?? 核心鐵律:必須加 :key!
千萬別偷懶!:key 是 Vue 識別節(jié)點(diǎn)身份的“身份證”。
- 作用:幫助 Vue 的 Diff 算法高效地更新 DOM。
- 避坑:盡量不要用 index 作為 key(除非列表是靜態(tài)的且沒有輸入框),最好用數(shù)據(jù)里唯一的 id。否則在列表排序或刪除時(shí),可能會(huì)出現(xiàn)渲染錯(cuò)誤或性能問題。
?? 巔峰對決:v-if 與 v-for 的優(yōu)先級戰(zhàn)爭
這是面試高頻考點(diǎn),也是新手最容易踩的坑!當(dāng)它們倆出現(xiàn)在同一個(gè)標(biāo)簽上時(shí),誰聽誰的?
答案取決于你的 Vue 版本!
Vue 2 時(shí)代:v-for 是老大
在 Vue 2 中,v-for 的優(yōu)先級高于 v-if。這意味著:Vue 會(huì)先循環(huán)生成所有的列表項(xiàng),然后再判斷每一項(xiàng)是否符合 v-if 的條件。
- 后果:即使你只想顯示幾個(gè)符合條件的項(xiàng),Vue 也會(huì)把整個(gè)列表遍歷一遍,造成不必要的性能浪費(fèi)。
Vue 3 時(shí)代:v-if 翻身做主人
在 Vue 3 中,v-if 的優(yōu)先級高于 v-for。這意味著:Vue 會(huì)先判斷條件。如果條件不滿足,它壓根就不會(huì)去執(zhí)行循環(huán)。
- 后果:雖然性能優(yōu)化了,但邏輯可能變得很奇怪——你可能想過濾列表,結(jié)果因?yàn)?v-if 先執(zhí)行,導(dǎo)致你訪問不到循環(huán)里的變量(比如 item.isActive),直接報(bào)錯(cuò)!
? 官方強(qiáng)烈建議:不要把它們寫在同一個(gè)標(biāo)簽上!
? 最佳實(shí)踐(無論 Vue 2 還是 3)
方法一:用計(jì)算屬性(Computed)過濾
這是最優(yōu)雅、性能最好的寫法。
<!-- 模板里只負(fù)責(zé)展示 -->
<ul>
<li v-for="user in activeUsers" :key="user.id">
{{ user.name }}
</li>
</ul>
<!-- 邏輯里負(fù)責(zé)過濾 -->
<script setup>
import { computed } from 'vue';
const users = ref([...]); // 原始數(shù)據(jù)
// 計(jì)算屬性自動(dòng)過濾出活躍用戶
const activeUsers = computed(() => {
return users.value.filter(user => user.isActive);
});
</script>
方法二:用 標(biāo)簽包裹
如果你不想用計(jì)算屬性,可以用一個(gè)不可見的 標(biāo)簽來承載 v-for。
<template v-for="user in users" :key="user.id">
<li v-if="user.isActive">
{{ user.name }}
</li>
</template>
?? 總結(jié)一下
| 特性 | v-if | v-show | v-for |
|---|---|---|---|
| 手段 | 動(dòng)態(tài)添加/移除 DOM | 切換 CSS display | 循環(huán)生成 DOM |
| 性能 | 初始渲染開銷小 | 初始渲染開銷大 | 需配合 :key |
| 場景 | 條件不常變 | 頻繁切換顯示 | 列表渲染 |
| 優(yōu)先級 | Vue3 高 / Vue2 低 | - | Vue2 高 / Vue3 低 |
一句話口訣
“列表過濾用計(jì)算,頻繁切換用 show,條件渲染用 if,key 值千萬別忘!”
好啦,今天的 Vue 指令大揭秘就到這里!是不是感覺思路清晰多了?趕緊去檢查一下你的代碼,把那些混用的 v-if 和 v-for 改過來吧!