iT邦幫忙

2024 iThome 鐵人賽

DAY 10
1
Modern Web

Vue 3 初學者:用實作帶你看過核心概念系列 第 10

Vue 3 用實作帶你看過核心概念 - Day 10:條件渲染 - v-if 與 v-show 的區別與應用

  • 分享至 

  • xImage
  •  

文章背景圖

目錄

  • v-if 條件渲染指令 - 單個元素
  • v-if 條件渲染指令 - 多個元素
  • v-show 條件渲染指令 - 單個元素
  • v-if vs v-show
  • 總結
  • 小試身手

v-if 條件渲染指令 - 單個元素

開發中遇到需要處理【如果是...就要...】的情境時,Vue 提供了 v-if 指令來幫助我們根據條件進行元素的渲染。這樣可以在特定條件滿足時動態地顯示或隱藏某些元素。

v-if 指令通過動態添加或移除 DOM 元素的方式來控制組件的顯示。當條件為true時,組件會被創建並插入到 DOM 中;當條件為false時,組件則會被銷毀並從 DOM 中移除。

在處理多個條件時,可以結合v-else-ifv-else指令來優化條件邏輯,使應用能夠根據不同情況渲染對應的內容:

  • v-if:當條件為true時渲染對應的元素。
  • v-else-if:可以有多個v-else-if指令。當前面的v-if條件為false且當前條件為true 時,渲染對應的元素。
  • v-else:當所有前面的v-ifv-else-if條件都為false時,渲染對應的元素。可以用於預設值的呈現。

👉 Vue3 Options API v-if、v-else-if 及 v-else 指令實作連結

以下透過一個漢堡點餐範例來說明:

  1. 在 Vue 實例中定義一個名為 status 的變數,該變數用來紀錄當前的點餐類型。
  2. 透過點擊按鈕來改變 status 的值,並紀錄當前選擇的餐點類型。
  3. 根據 status 的變化,模板動態顯示對應的文字描述,告訴使用者當前根據選擇餐點的心情描述。

v-if 動態新增 DOM 元素

Vue Template:

<div id="app">
  <h1>當前飢餓狀態</h1>
  <h2 v-if="status === 'large'">
    吃得飽飽的,真開心!
  </h2>
  <h2 v-else-if="status === 'midium'">
    肚子不會餓,但還有點嘴饞!
  </h2>
  <h2 v-else-if="status === 'small'">
    吃太少反而更想吃QQ
  </h2>
  <h2 v-else>
    可以點餐吃了嗎?好餓!
  </h2>
  <div class="container">
    🍔 點餐櫃檯
    <div class="product-item">
      <p>餐點說明:漢堡 + 中薯 + 中杯可樂</p>
      <button @click="orderFood('large')">大麥克套餐</button>
    </div>
    <div class="product-item">
      <p>餐點說明:小杯可樂 + 法式芥末香鷄堡</p>
      <button @click="orderFood('midium')">1 + 1 套餐</button>
    </div>
    <div class="product-item">
      <p>餐點說明:小薯</p>
      <button @click="orderFood('small')">單點小薯</button>
    </div>
  </div>
</div>

javaScript:

const rootComponent = {
  data(){
    return{
      status: '',
    }
  },
  methods:{
    // 點餐行動
    orderFood(type){
      this.status = type;
    }
  }
}

這部分也可以使用計算屬性進行改寫,使模板變得更簡潔和易於閱讀。

計算屬性可以將條件邏輯從模板中分離出來,避免直接在模板中編寫過多的邏輯判斷,從而提升代碼的可維護性與可讀性。這樣的改寫方式有助於保持模板的乾淨簡明,讓條件處理變得更加清晰。

👉 Vue3 Options API 使用計算屬性改寫實作連結

部分 Vue Template:

  <h2>
    {{ getDescription }}
  </h2>
  ...略

部分 JavaScript:

  computed: {
    getDescription() {
      if (this.status === "large") {
        return "吃得飽飽的,真開心!";
      } else if (this.status === "midium") {
        return "肚子不會餓,但還有點嘴饞!";
      } else if (this.status === "small") {
        return "吃太少反而更想吃QQ";
      } else {
        return "可以點餐吃了嗎?好餓!";
      }
    }
  }
  ...略

v-if 條件渲染指令 - 多個元素

v-if指令必須綁定在具體的元素上,但如果需要根據條件渲染多個元素的區塊,無法直接將v-if應用於多個元素。

要實現多個元素的條件渲染,可以使用<template>標籤來包裹這些元素。<template>標籤本身不會被渲染到 HTML DOM 中,而是作為一個不可見的包裹容器,用於根據條件動態渲染整個區塊的內容。這樣可以方便地對多個元素進行條件判斷,而不影響實際的 DOM 結構。

以下用文章專欄的範例,說明template標籤根據條件渲染區塊的情形:

Template 標籤僅在符合條件渲染內容

👉 Vue3 Options API template標籤搭配 v-if、v-else 指令使用實作連結

Vue Template:

<div id="app">
  <div class="container">
  
    <template v-if="selectSection === 'section1'">
      <section class="section1">
        <h2>勝利專欄</h2>
        <div class="content">
          Lorem, ipsum dolor sit amet consectetur adipisicing elit. Vel nam debitis ut?
        </div>
      </section>
    </template>
    
    <template v-else>
      <section v-else class="section2" v-else>
        <h2>失敗專欄</h2>
        <div class="content">
          Ad mollitia fugit, facilis, nulla veritatis harum libero nobis non magnam deleniti eius omnis atque id in.
        </div>
      </section>
    </template>
    
    <button @click="changeSection" type="button" class="mt-4">切換顯示不同文章區塊</button>
  </div>
</div>

JavaScript:

const rootComponent = {
  data(){
    return{
      selectSection: 'section1'
    }
  },
  methods:{
    changeSection(){
      return this.selectSection = this.selectSection === 'section1' ? 'section2' : 'section1';
    }
  }
}

v-show 條件渲染指令 - 單個元素

v-show 指令通過設置CSS display屬性來控制元素的顯示與隱藏。

用法與v-if相近,但有以下限制:

  1. v-show 不能應用在template標籤上,因為 template 本身不會渲染為具體的 DOM 元素。
  2. v-show 不能與v-else-ifv-else指令結合使用,因為它只控制當前元素的顯示與隱藏。

以下將以彈窗案例舉例:

  1. 定義一個變數 showModal 來控制彈窗的顯示狀態。
  2. 當按下按鈕時,切換 showModal 的值來顯示或隱藏彈窗畫面。

v-show 指令調整 DOM 元素 display 變化

👉 Vue3 Options API v-show 顯示彈窗實作連結

Vue Template:

<div id="app">
  <button @click="changeModal">切換彈窗</button>
  <div v-show="showModal" class="modal ">
    這是個對話框
  </div>
</div>

JavaScript:

const rootComponent = {
  data() {
    return{
      showModal: false
    }
  },
  methods:{
    changeModal(){
      this.showModal = !this.showModal;
    }
  }
}

v-if vs v-show

  • 初始成本
    • v-if:當初始化邏輯條件為 false 時,不會創建對應的 DOM 元素,可以降低初始渲染的開銷。
    • v-show:不論條件是否滿足,都會創建 DOM 元素,只是透過 CSS display 來控制顯示或隱藏,因此初始渲染的成本較高。
  • 切換成本
    • v-if:切換成本較高,因為每次條件變化時都會銷毀並重新創建組件實例。
    • v-show:切換成本較低,因為元素始終保留在 DOM 中,只是透過 CSS 控制顯示或隱藏,不會銷毀組件。

總結

  • v-if 指令:適用於不頻繁切換的場景。可以與v-else-ifv-else指令搭配使用,當涉及多個元素區塊的切換時,可以使用<template>標籤來包裹這些區塊,以達到條件渲染效果。
  • v-show 指令:適合頻繁切換顯示狀態的場景,通過控制CSS display屬性來顯示或隱藏元素。它無法與v-else-ifv-else一起使用,也不能應用在<template>標籤上。

小試身手

練習上面使用的v-ifv-else試著完成今天的小練習。

根據不同登入狀態決定要顯示的導覽列會員身份是訪客還是已登入狀態,僅需調整template的部分。

👉 Vue3 Options API v-if 和 v-else 登入練習模板連結
👉 Vue3 Options API v-if 和 v-else 登入練習完成版實作連結


上一篇
Vue 3 用實作帶你看過核心概念 - Day 9:Class 與 Style 的樣式綁定
下一篇
Vue 3 用實作帶你看過核心概念 - Day 11:v-for 指令的基本與進階應用
系列文
Vue 3 初學者:用實作帶你看過核心概念30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言