iT邦幫忙

2024 iThome 鐵人賽

DAY 19
0
Modern Web

欸你是要進 Vue 了沒?系列 第 19

欸你是要進 Vue 了沒? - Day19:Vue 條件渲染家族 v-if、v-else-if、v-else、v-show

  • 分享至 

  • xImage
  •  

今天我們進入「條件渲染」的章節囉~
將分為兩部分講解:

  • v-ifv-else-ifv-else
  • v-show

/images/emoticon/emoticon78.gif/images/emoticon/emoticon78.gif/images/emoticon/emoticon78.gif/images/emoticon/emoticon78.gif

OK,請開始我的表演。

定義

Vue 的條件渲染提供了「v-ifv-else-ifv-elsev-show」語法,我們可以利用它實現「動態決定網頁上要顯示哪一部分內容」。

v-if、v-else-if、v-else

邏輯概念和 JS 判斷式相同:

  • 當條件成立時,會進入 v-if 區塊並渲染對應的內容。
  • 如果 v-if 條件不成立,則會檢查 v-else-if 區塊(如果有的話),並根據條件渲染對應內容。
  • 若所有條件都不符合,最後會進入 v-else 區塊並渲染其內容。

可以這樣理解:

<div v-if="conditionA">區塊一</div>
<div v-else-if="conditionB">區塊二</div>
<div v-else>區塊三</div>

if (conditionA) {
  渲染區塊一
} else if (conditionB) {
  渲染區塊二
} else {
  渲染區塊三
}

語法

渲染條件基於 "" 中的表達式是否成立(return true)。

v-if

v-if="表達式"

條件成立,該區塊會被渲染,反之不會(或進入下個條件判斷)。

v-else

v-else="表達式"

v-ifv-else-if(若有) 的條件都不成立時,會渲染 v-else 區塊。

特點:不能單獨存在,必須緊跟在 v-ifv-else-if 之後。

v-else-if

v-else-if="表達式"

v-if 的條件不成立時,會渲染 v-else-if

特點:

  1. 可以有無限多個並重複使用。
  2. 不能單獨存在,必須緊跟在 v-if 之後。
  3. 不是必要的,當只需判斷一個條件時,可以只用 v-ifv-else

我們可以用一些範例來更認識它們!

v-if 範例

定義兩個 <h3>,使用 v-if 語法,分別綁定真值/假值。

<script setup>
import { ref } from "vue";

const cute = ref(true);
const naughty = ref(false);
</script>
<template>
  <h3 v-if="cute">Sprouts is CUTE!</h3>
  <h3 v-if="naughty">Sprouts is NAUGHTY!</h3>
</template>

cutetrue,因此 <h3 v-if="cute">Sprouts is CUTE!</h3> 區塊會被渲染。

瀏覽器會呈現:
https://ithelp.ithome.com.tw/upload/images/20241002/20169139Q3rw5ul2Yg.png

v-else 範例

定義一個按鈕,點擊了會更改 v-if 為反值(就不渲染),因而渲染 v-else 區塊。

<script setup>
import { ref } from "vue";

const cute = ref(true);
const changeMind = function () {
  cute.value = !cute.value;
};
</script>
<template>
  <img v-if="cute" src="./cute.png" />
  <img v-else src="./naughty.png" />
  <h3 v-if="cute">Sprouts is CUTE!</h3>
  <h3 v-else>Sprouts is NAUGHTY!</h3>
  <button @click="changeMind">改變心意鈕</button>
</template>

button 綁定了click 事件,點擊按鈕後會觸發 changeMind 函式,將 cute 響應式狀態的值改為相反,true 變為 false,因此v-else 的區塊會被渲染。

瀏覽器會呈現:

注意必須緊鄰在 v-if 區塊後。
https://ithelp.ithome.com.tw/upload/images/20241002/20169139SdDzHQ84Iw.png

v-else-if 範例

增加 v-else-if 區塊試試看!

<script setup>
import { ref } from "vue";

const howSproutsIs = ref("cute");
</script>
<template>
  <h3 v-if="howSproutsIs === 'cute'">Sprouts is CUTE!</h3>
  <h3 v-else-if="howSproutsIs === 'quiet'">Sprouts is QUIET!</h3>
  <h3 v-else-if="howSproutsIs === 'lazy'">Sprouts is LAZY!</h3>
  <h3 v-else>Sprouts is NAUGHTY!</h3>
</template>

在此,我們將 v-ifv-else-if 更改為了表達式,而 howSproutsIs 響應式綁定了 "cute",因此在 v-if 區塊的條件成立(就不進入接下來的條件了),預設會顯示 Sprouts is CUTE!

以上程式碼也可以想成這樣:

if(howSproutsIs === 'cute') {
  渲染 Sprouts is CUTE!
} else if (howSproutsIs === 'quiet') {
  渲染 Sprouts is QUIET!
} else if (howSproutsIs === 'lazy') {
  渲染 Sprouts is LAZY!
} else {
  渲染 Sprouts is NAUGHTY!
}

因此如果我們更改 howSproutsIs 的值,又會重新進入條件判斷。

觀察渲染的結果:

我們再把 貓咪系統 完善一下 XD

changeMind 函式中添加一些邏輯,讓點選按鈕後可以做到更多切換:

<script setup>
import { ref } from "vue";

const howSproutsIs = ref("cute");

const changeMind = function () {
  // 根據目前的狀態來改變 Sprouts 的狀態
  if (howSproutsIs.value === "cute") {
    howSproutsIs.value = "quiet";
  } else if (howSproutsIs.value === "quiet") {
    howSproutsIs.value = "lazy";
  } else if (howSproutsIs.value === "lazy") {
    howSproutsIs.value = "naughty";
  } else {
    howSproutsIs.value = "cute";
  }
};
</script>
<template>
  <img v-if="howSproutsIs === 'cute'" src="./cute.png" />
  <img v-else-if="howSproutsIs === 'quiet'" src="./quiet.png" />
  <img v-else-if="howSproutsIs === 'lazy'" src="./lazy.png" />
  <img v-else src="./naughty.png" />
  <h3 v-if="howSproutsIs === 'cute'">Sprouts is CUTE!</h3>
  <h3 v-else-if="howSproutsIs === 'quiet'">Sprouts is QUIET!</h3>
  <h3 v-else-if="howSproutsIs === 'lazy'">Sprouts is LAZY!</h3>
  <h3 v-else>Sprouts is NAUGHTY!</h3>
  <button @click="changeMind">改變心意鈕</button>
</template>

和以上範例是同樣的概念,渲染的條件取決於綁定之表達式的真/假值。

瀏覽器上將會呈現:

在組件使用

v-if 可以直接用來控制是否渲染 <template>
<template> 中若有多個區塊需要被渲染/不被渲染,可以這麼寫:

<template>
  <template v-if="conditionA">
    <div>區塊一</div>
    <div>區塊二</div>
    <div>區塊三</div>
  </template>
  
  <template v-else-if="conditionA">
    <div>區塊一</div>
    <div>區塊二</div>
    <div>區塊三</div>
  </template>

  <template v-else>
    <div>區塊一</div>
    <div>區塊二</div>
    <div>區塊三</div>
  </template>
</template>

v-show

語法

渲染條件基於 "" 中的表達式是否成立(return true)。

v-show="表達式"

特點:

  1. 運作原理為切換元素的 display 屬性,表達式 return false 時,切換為 none
  2. 會在 DOM 渲染中保留綁定的元素(即使條件不成立)。
  3. 不能和 v-else 一起使用。
  4. 不能在 <template> 元素上使用。

範例

定義兩個 <h3>,使用 v-if 語法,分別綁定真值/假值。

<script setup>
import { ref } from "vue";

const cute = ref(true);
const naughty = ref(false);
</script>
<template>
  <h3 v-show="cute">Sprouts is CUTE!</h3>
  <h3 v-show="naughty">Sprouts is NAUGHTY!</h3>
</template>

cutetrue,因此 <h3 v-if="cute">Sprouts is CUTE!</h3> 區塊會被渲染。

瀏覽器會呈現:
https://ithelp.ithome.com.tw/upload/images/20241002/20169139sxJCpUcHYk.png
可以注意到:綁定 naughty 的區塊,displaynone
因此:元素在初始渲染時皆會被加入到 DOM 中,即使它的顯示狀態是 none

實際感受一下,元素綁定真/假值時,影響 display 切換的渲染行為:

v-if 和 v-show

官方文件:
v-if 是“真實的”按條件渲染,因為它確保了在切換時,條件區塊內的事件監聽器和子組件都會被銷毀與重建。

v-if 也是惰性的:如果在初次渲染時條件值為 false,則不會做任何事。條件區塊只有當條件首次變為 true 時才被渲染。

相比之下,v-show 簡單許多,元素無論初始條件如何,始終會被渲染,只有 CSS display 屬性會被切換。

總的來說,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。因此,如果需要頻繁切換,則使用 v-show 較好;如果在運行時綁定條件很少改變,則 v-if 會更合適。

我們整理一下兩者區別:

特性 v-if v-show
行為 切換時會銷毀/重建元素 始終渲染元素,只切換 display 屬性
初次渲染 條件為 true 才渲染 元素始終渲染
切換開銷 較高 較低
初始渲染開銷 較低 較高
適用情景 條件變動少、不頻繁切換的 條件變動多、頻繁切換的

v-if 和 v-for

官方文件這邊說不推薦兩者同時使用,因為同時存在時,v-if 會首先被執行。
(淺淺帶過⋯⋯明天我們就會講到 v-for 囉)

小結

https://ithelp.ithome.com.tw/upload/images/20241002/20169139ZI8OBTZ74Z.png

雖然 GPT 有點胡言亂語,但我學這章的時候真的蠻開心的:)
(開心就好)

明天~~我們來看列表渲染拉!
/images/emoticon/emoticon37.gif

範例 code ⬇️

https://github.com/Jamixcs/2024iThome-jamixcs/tree/main/src/components/day19

參考資料


上一篇
欸你是要進 Vue 了沒? - Day18:Vue 屬性綁定之 class && style 功能增強系列(style 篇)
下一篇
欸你是要進 Vue 了沒? - Day20:Vue 列表渲染之那個很會幫主管列資料的 v-for 同事
系列文
欸你是要進 Vue 了沒?22
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言