跳至主要內容
Skip to content

v-if 與 v-show 的區別

v-ifv-show 都能控制元素是否顯示,但它們的底層行為完全不同。面試裡如果只回答「v-if 是條件渲染,v-show 是 display none」,通常還不夠。

一句話回答:v-if 會真正建立或銷毀 DOM 與元件;v-show 會保留 DOM,只透過 CSS 的 display 控制顯示與隱藏。


一、 必考觀念

1. v-if 是條件渲染

v-if 條件為 false 時,對應的 DOM 不會被建立。

vue
<template>
  <UserPanel v-if="isLogin" />
</template>

如果 isLoginfalseUserPanel 不會掛載。當 isLogin 變成 true 時,Vue 才會建立這個元件並插入 DOM。

可以簡化理解成:

javascript
if (isLogin) {
  mount(UserPanel)
} else {
  unmount(UserPanel)
}

所以 v-if 控制的是「有沒有這個節點」。

2. v-show 是顯示切換

v-show 不會移除 DOM,它只是切換元素的 display

vue
<template>
  <UserPanel v-show="isLogin" />
</template>

即使 isLoginfalseUserPanel 仍然會被建立,只是被加上:

css
display: none;

可以簡化理解成:

javascript
el.style.display = isLogin ? '' : 'none'

所以 v-show 控制的是「這個節點看不看得到」。

3. 初始成本與切換成本

兩者最重要的取捨是成本不同。

指令初始成本切換成本
v-if條件為 false 時較低,因為不建立 DOM較高,因為要 mount / unmount
v-show較高,因為一開始就建立 DOM較低,因為只切換 display

簡單判斷:

  • 條件很少改變:用 v-if
  • 需要頻繁切換:用 v-show

4. 生命週期差異

如果 v-if 用在元件上,條件切換會影響元件生命週期。

vue
<UserPanel v-if="visible" />

visiblefalse 變成 true

text
setup / created
-> beforeMount
-> mounted

visibletrue 變成 false

text
beforeUnmount
-> unmounted

v-show 不會反覆掛載與卸載元件。它只是改 CSS,因此元件狀態會保留。

這也代表:

  • v-if 重新顯示時,內部狀態可能重新初始化。
  • v-show 重新顯示時,內部狀態通常還在。

5. DOM 與 Template Refs 差異

因為 v-if 為 false 時 DOM 不存在,所以你不能保證 ref 一定有值。

vue
<template>
  <input v-if="visible" ref="inputRef" />
</template>

如果 visiblefalse

typescript
inputRef.value // null

v-show 則不同,DOM 一開始就存在:

vue
<template>
  <input v-show="visible" ref="inputRef" />
</template>

即使看不見,ref 通常仍可取得 DOM 元素。


二、 追問題庫

Q1:v-ifv-show 最大差異是什麼?

v-if 是條件渲染,會建立或銷毀 DOM。v-show 是顯示切換,DOM 一直存在,只透過 display: none 隱藏。

Q2:什麼情況用 v-if

適合:

  • 條件不常變。
  • 初始狀態通常不顯示。
  • 元件很重,不希望一開始就建立。
  • 權限控制,不符合條件時不應該出現在 DOM。
  • 切換時希望重新初始化狀態。

例如:

vue
<AdminPanel v-if="user.role === 'admin'" />

如果不是管理員,這個區塊就不應該被建立。

Q3:什麼情況用 v-show

適合:

  • 頻繁切換顯示狀態。
  • Tab 內容、Dropdown、Tooltip、展開收合。
  • 想保留 DOM 狀態或元件內部狀態。
  • 切換成本比初始渲染成本更重要。

例如:

vue
<DropdownMenu v-show="opened" />

Dropdown 可能會頻繁開關,用 v-show 可以避免每次都 mount / unmount。

Q4:v-show 能用在 <template> 上嗎?

不行。

v-show 的本質是修改元素的 display,所以它需要真實 DOM 元素。<template> 本身不會渲染成 DOM,因此不能用 v-show

vue
<!-- 不適合 -->
<template v-show="visible">
  <p>content</p>
</template>

如果你需要控制一組節點是否渲染,可以用 v-if

vue
<template v-if="visible">
  <p>content</p>
</template>

或包一層真實元素:

vue
<div v-show="visible">
  <p>content</p>
</div>

Q5:v-ifv-for 可以一起用嗎?

不建議放在同一個元素上。

vue
<!-- 不建議 -->
<li
  v-for="item in list"
  v-if="item.visible"
  :key="item.id"
>
  {{ item.name }}
</li>

比較好的做法是先用 computed 過濾:

typescript
const visibleList = computed(() => {
  return list.value.filter(item => item.visible)
})
vue
<li
  v-for="item in visibleList"
  :key="item.id"
>
  {{ item.name }}
</li>

這樣意圖更清楚,也避免每次渲染時把判斷混在模板裡。

Q6:v-ifv-show 對 CSS transition 有差嗎?

有。

v-if 是元素進入與離開 DOM,通常對應 enter / leave transition。

v-show 是 display 切換,也可以搭配 <Transition>,但它不會銷毀元素,適合做顯示隱藏的過渡。

如果是高度、透明度、位置動畫,還要考慮瀏覽器渲染成本。可以延伸讀:瀏覽器渲染管線與 DOM 操作成本


三、 實作題

題目:Modal 應該用 v-if 還是 v-show

假設有一個 Modal:

vue
<Modal v-if="opened" />

或:

vue
<Modal v-show="opened" />

你會怎麼選?

答案不是固定的,要看需求。

情境一:很少打開,內容很重

例如 Modal 裡有大量表單、圖表、API 請求或第三方套件。

vue
<Modal v-if="opened" />

理由:

  • 初始不建立,減少首屏成本。
  • 關閉時卸載,釋放部分資源。
  • 下次打開可以重新初始化。

情境二:頻繁開關,需要保留狀態

例如使用者正在填表,關閉後再打開,希望內容還在。

vue
<Modal v-show="opened" />

理由:

  • DOM 和元件狀態保留。
  • 開關切換成本低。
  • 不會每次重新跑 mounted 邏輯。

情境三:需要兼顧初始成本與狀態保留

可以用「第一次打開才建立,之後用 v-show 切換」:

vue
<Modal
  v-if="hasOpened"
  v-show="opened"
/>
typescript
watch(opened, (value) => {
  if (value) {
    hasOpened.value = true
  }
})

這個模式適合比較重、但開過後希望保留狀態的元件。


四、 資深視角

1. 指令選擇背後是資源管理

v-ifv-show 的差異,不只是「有沒有 display none」。它其實是在問:

  • 要不要建立這個 DOM?
  • 元件狀態要不要保留?
  • 副作用要不要跟著清理?
  • 首屏成本重要,還是切換成本重要?
  • 這個元素隱藏時能不能被使用者或輔助技術接觸到?

這些都是資源管理與互動語意問題。

2. 權限控制更適合 v-if

如果一個區塊不應該被某些使用者看到,v-if 通常比 v-show 更合理。

vue
<DeleteButton v-if="canDelete" />

v-show 只是視覺隱藏,DOM 仍存在。雖然前端本來就不能作為真正安全邊界,但在 UI 語意上,不該出現的東西就不要渲染。

真正的權限仍然要由後端驗證。

3. 效能問題要看整體場景

如果一個元素很小,v-ifv-show 的差異通常不重要。

真正需要在意的是:

  • 大型組件。
  • 切換頻率高。
  • 內部有昂貴初始化。
  • 隱藏區塊裡有大量子節點。
  • 切換時有動畫或 layout 變化。

所以面試回答不要絕對化。說「頻繁切換用 v-show,不頻繁用 v-if」是基本答案;能補上狀態保留、生命週期、首屏成本與權限語意,才是更完整的答案。


總結

面向v-ifv-show
本質條件渲染CSS 顯示切換
DOMfalse 時不存在永遠存在
初始成本條件 false 時較低較高
切換成本較高較低
生命週期會 mount / unmount不會反覆 mount / unmount
狀態保留通常不保留通常保留
支援 <template>支援不支援
適合場景不常切換、權限控制、延後建立頻繁切換、Tab、Dropdown、狀態保留

一句完整的面試回答可以是:

v-if 是真正的條件渲染,條件為 false 時 DOM 和元件都不會建立,切換時會觸發 mount / unmount,所以初始成本低但切換成本高。v-show 會先建立 DOM,只透過 display: none 控制顯示,切換成本低且能保留元件狀態,但初始成本較高。實務上,不常切換或權限控制用 v-if,頻繁切換或需要保留狀態用 v-show

延伸閱讀