本文 AI 產出,尚未審核

Vue3 – Transition 元件基本用法

簡介

在單頁應用 (SPA) 中,畫面切換與資料變化往往是頻繁且即時的。若沒有適當的過渡效果,使用者會感受到突兀的「跳躍」感,降低介面的可用性與美觀度。Vue 3 提供的 <transition> 元件,讓開發者只需要少量的宣告,就能為元素或組件加入 CSS 或 JavaScript 動畫,且支援進出、進入、離開等多種狀態。掌握它的基本用法,不僅能提升使用者體驗,還能在開發過程中保持 可讀性可維護性

本篇文章將從概念說明、實作範例、常見陷阱與最佳實踐,最後帶入實務應用場景,幫助從初學者到中級開發者快速上手 Vue 3 的 <transition>


核心概念

1. <transition> 的工作原理

<transition> 會在其包裹的元素或子組件 進入 (enter)離開 (leave) 時,自動為目標元素加入、移除 CSS class。這些 class 依序為:

階段 加入的 class 移除的 class
進入開始 (enter-from) v-enter-from v-enter-active
進入過程 (enter-active) v-enter-active -
進入結束 (enter-to) v-enter-to v-enter-active
離開開始 (leave-from) v-leave-from v-leave-active
離開過程 (leave-active) v-leave-active -
離開結束 (leave-to) v-leave-to v-leave-active

預設的 class 前綴是 v-,可以透過 name 屬性自訂,例如 name="fade" 後,產生的 class 會是 fade-enter-fromfade-leave-to 等。

重點:只要在 CSS 中為這些 class 定義 transitionanimation,Vue 便會在正確的時機觸發動畫。

2. 基本語法

<template>
  <button @click="show = !show">Toggle</button>

  <transition name="fade">
    <p v-if="show">這段文字會淡入淡出</p>
  </transition>
</template>

<script setup>
import { ref } from 'vue'
const show = ref(false)
</script>

上述範例中,<p> 元素在 showtrue 時插入 DOM,為 false 時移除。<transition> 會根據 fade 名稱自動套用對應的 CSS。

3. CSS 範例

/* fade 進入 */
.fade-enter-from { opacity: 0; }
.fade-enter-active { transition: opacity 0.4s ease; }
.fade-enter-to   { opacity: 1; }

/* fade 離開 */
.fade-leave-from { opacity: 1; }
.fade-leave-active { transition: opacity 0.4s ease; }
.fade-leave-to   { opacity: 0; }

只要寫好這六個 class,Vue 就會在元素掛載與卸載的過程中完成淡入淡出。


程式碼範例

以下提供 5 個常見且實用的範例,每個範例都會說明要點與可自行調整的參數。

範例 1️⃣ 簡易淡入淡出(上文已示)

<template>
  <button @click="visible = !visible">Toggle Box</button>

  <transition name="fade">
    <div v-if="visible" class="box">Box</div>
  </transition>
</template>

<script setup>
import { ref } from 'vue'
const visible = ref(false)
</script>

<style scoped>
.box {
  width: 120px;
  height: 120px;
  background: #42b983;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* fade 動畫 */
.fade-enter-from { opacity: 0; transform: scale(0.8); }
.fade-enter-active { transition: opacity .3s, transform .3s; }
.fade-enter-to   { opacity: 1; transform: scale(1); }

.fade-leave-from { opacity: 1; transform: scale(1); }
.fade-leave-active { transition: opacity .3s, transform .3s; }
.fade-leave-to   { opacity: 0; transform: scale(0.8); }
</style>

說明:同時使用 opacitytransform,讓盒子在淡入時有縮放的感覺,提升視覺層次。


範例 2️⃣ 列表項目逐一淡入(使用 appear

<template>
  <transition-group name="list" tag="ul" appear>
    <li v-for="item in items" :key="item.id" class="item">
      {{ item.text }}
    </li>
  </transition-group>
</template>

<script setup>
import { ref } from 'vue'
const items = ref([
  { id: 1, text: 'Vue' },
  { id: 2, text: 'React' },
  { id: 3, text: 'Angular' }
])
</script>

<style scoped>
.list-enter-from { opacity: 0; transform: translateY(20px); }
.list-enter-active { transition: all .4s ease; }
.list-enter-to   { opacity: 1; transform: translateY(0); }

.list-leave-from { opacity: 1; transform: translateY(0); }
.list-leave-active { transition: all .4s ease; }
.list-leave-to   { opacity: 0; transform: translateY(-20px); }
</style>

要點

  • 使用 <transition-group> 處理 多元素 的過渡。
  • appear 讓組件在首次渲染時也套用進入動畫。
  • 必須為每個子元素提供唯一的 key,否則 Vue 無法正確追蹤。

範例 3️⃣ 自訂過渡名稱與持續時間

<template>
  <button @click="show = !show">切換</button>

  <transition name="slide" mode="out-in" :duration="500">
    <div v-if="show" class="panel">滑動面板</div>
  </transition>
</template>

<script setup>
import { ref } from 'vue'
const show = ref(false)
</script>

<style scoped>
.slide-enter-from { transform: translateX(-100%); }
.slide-enter-active { transition: transform 0.5s ease; }
.slide-enter-to   { transform: translateX(0); }

.slide-leave-from { transform: translateX(0); }
.slide-leave-active { transition: transform 0.5s ease; }
.slide-leave-to   { transform: translateX(100%); }
</style>

說明mode="out-in" 確保舊的元素離開完畢後才插入新的元素,常用於 頁面切換duration 可直接在 <transition> 上設定,以免在 CSS 中硬編碼時間。


範例 4️⃣ 使用 JavaScript Hook 控制動畫

<template>
  <button @click="show = !show">Toggle</button>

  <transition
    @before-enter="beforeEnter"
    @enter="enter"
    @leave="leave"
  >
    <div v-if="show" class="js-box">JS 動畫盒子</div>
  </transition>
</template>

<script setup>
import { ref } from 'vue'

const show = ref(false)

function beforeEnter(el) {
  el.style.opacity = 0
  el.style.transform = 'scale(0.5)'
}
function enter(el, done) {
  // 使用 requestAnimationFrame 確保樣式變更被瀏覽器捕捉
  requestAnimationFrame(() => {
    el.style.transition = 'all 0.4s ease'
    el.style.opacity = 1
    el.style.transform = 'scale(1)'
    // 動畫結束時呼叫 done
    el.addEventListener('transitionend', done, { once: true })
  })
}
function leave(el, done) {
  el.style.transition = 'all 0.4s ease'
  el.style.opacity = 0
  el.style.transform = 'scale(0.5)'
  el.addEventListener('transitionend', done, { once: true })
}
</script>

<style scoped>
.js-box {
  width: 150px;
  height: 150px;
  background: #ff6f61;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>

重點

  • 當 CSS 無法滿足需求(例如根據資料動態計算高度)時,可改用 JavaScript Hook
  • done 必須在動畫結束時呼叫,否則 Vue 會認為過渡仍在進行,導致元素卡住。

範例 5️⃣ 動態切換過渡類型(利用 :name

<template>
  <div class="controls">
    <label>過渡類型:
      <select v-model="type">
        <option value="fade">淡入淡出</option>
        <option value="zoom">縮放</option>
        <option value="slide">滑動</option>
      </select>
    </label>
    <button @click="show = !show">Toggle</button>
  </div>

  <transition :name="type">
    <div v-if="show" class="box">{{ type }} 效果</div>
  </transition>
</template>

<script setup>
import { ref } from 'vue'
const show = ref(false)
const type = ref('fade')
</script>

<style scoped>
.box {
  width: 200px;
  height: 80px;
  background: #5c6bc0;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* fade */
.fade-enter-from, .fade-leave-to { opacity: 0; }
.fade-enter-active, .fade-leave-active { transition: opacity .3s; }

/* zoom */
.zoom-enter-from, .zoom-leave-to { transform: scale(0.5); opacity: 0; }
.zoom-enter-active, .zoom-leave-active { transition: transform .3s, opacity .3s; }
.zoom-enter-to, .zoom-leave-from { transform: scale(1); opacity: 1; }

/* slide */
.slide-enter-from { transform: translateX(-100%); }
.slide-enter-active { transition: transform .4s ease; }
.slide-enter-to { transform: translateX(0); }
.slide-leave-from { transform: translateX(0); }
.slide-leave-active { transition: transform .4s ease; }
.slide-leave-to { transform: translateX(100%); }
</style>

說明:透過 :name 綁定變數,使用者可以即時切換不同的過渡效果,適合 設定頁面主題切換 的情境。


常見陷阱與最佳實踐

陷阱 可能的結果 解決方式 / 最佳實踐
忘記設定唯一 key(在 <transition-group> 列表變化時動畫失效或出現錯位 為每個子項目提供穩定且唯一的 key(如資料庫 ID)
過渡時間與 CSS transition 時間不一致 動畫卡住、enter/leave 事件不觸發 done 使用 <transition>duration 屬性或在 CSS 中明確寫出時間,保持一致
v-ifv-show 同時使用 v-show 直接改變 display,會讓 <transition> 無法捕捉離開階段 僅使用 v-if(真正的掛載/卸載)或在需要快速切換時改為 v-show 並自行處理過渡
在過渡期間改變元素尺寸 會導致瀏覽器重新計算布局,動畫卡頓 若需要尺寸變化,建議改用 transition 搭配 max-height 或使用 JavaScript Hook 手動控制
過渡層級過深(多層 <transition> 產生不必要的重繪,效能下降 只在必要的外層套用 <transition>,內層若不需要可直接使用 CSS 動畫

最佳實踐

  1. 盡量使用 CSS:除非有特別需求,CSS 動畫的效能遠高於 JavaScript。
  2. 命名規則統一:使用 name 屬性或自訂前綴,保持樣式檔案可讀性。
  3. 分離動畫與布局:避免在過渡期間同時改變 displayposition 等會觸發重排的屬性。
  4. 使用 mode="out-in":在切換路由或卡片時,確保舊內容先離開再進入,避免閃爍。
  5. 測試不同裝置:手機瀏覽器的硬體加速與桌面不同,適當調整 transition-timing-function(如 cubic-bezier)提升感受。

實際應用場景

場景 需求 建議的 <transition> 用法
表單驗證錯誤提示 錯誤訊息出現時淡入、消失時淡出 包裹錯誤訊息 <transition name="fade">,搭配 v-if 顯示/隱藏
側邊選單 (Drawer) 點擊按鈕時滑入,關閉時滑出 使用 name="slide"mode="out-in",可加上 .slide-enter-active 設定 transform
圖片輪播 圖片切換時使用淡入淡出或縮放 <transition-group> 搭配 key 為圖片 URL,使用 appear 讓首張圖也有過渡
路由切換 (Vue Router) 每次切換頁面時有統一的過渡效果 App.vue 中包裹 <router-view><transition name="route-fade" mode="out-in">
動態表格資料更新 新增列時滑入、刪除列時滑出 <transition-group tag="tbody">,為每列 <tr> 設定唯一 key,定義 enter/leave 動畫

透過上述範例,可見 <transition> 在日常開發中幾乎無所不在,僅需少量設定即可大幅提升介面的 流暢度專業感


總結

Vue 3 的 <transition> 元件提供了 聲明式彈性 的動畫機制,讓開發者能在 進入、離開、切換 等多種情境下,快速套用 CSS 或 JavaScript 動畫。掌握以下要點,即可在專案中安全且有效地使用:

  • 了解 六個自動產生的 class(enter/leave 系列),並以 name 或自訂前綴管理樣式。
  • 使用 <transition-group> 處理多元素過渡,務必提供唯一 key
  • 依需求選擇 CSSJavaScript Hook,CSS 為首選,JS 為例外。
  • 注意 durationmodeappear 等屬性,避免動畫卡頓或錯誤。
  • 在實務上,從表單驗證、抽屜、輪播、路由切換到動態表格,都能透過 <transition> 讓 UI 更具「活力」與「可用性」。

只要遵循 最佳實踐,並根據實際需求微調過渡時間與曲線,Vue 3 的過渡效果將成為你開發現代 Web 應用時不可或缺的利器。祝你在專案中玩出各式炫麗動畫,為使用者帶來更佳的體驗!