iT邦幫忙

2025 iThome 鐵人賽

DAY 25
0
Vue.js

需求至上的 Vue 魔法之旅系列 第 25

Day 18: 過場魔法:讓畫面不再閃爍,流暢如吟唱的法咒

  • 分享至 

  • xImage
  •  

前言

在魔法學院裡,有個小秘密:
真正的高階魔法師,不只是讓咒語發動,更要讓過程優雅

你是否曾經打開一個網站,點下按鈕後畫面突然「啪!」地一閃?
那種突兀的切換,就像傳送門在你腳邊炸開一樣,讓人心頭一震。

雖然功能正確,但那份「突兀感」會讓使用者的體驗失去魔力。
而如果能在切換時淡入淡出、滑入滑出,就能讓畫面像吟唱的魔法詩篇——
平滑、自然、流動。

今天,我們將學習 Vue 的過場魔法(Transition Magic)
<Transition><TransitionGroup> 讓你的飲料系統「動起來」,
讓點單的每一步都充滿柔和的魔法氣息

其實我們今天要學的東西就是轉場動畫
不過我們不會講得特別複雜

會把顯示的畫面淡淡的顯示淡入這樣/images/emoticon/emoticon01.gif


一、User Story(魔法需求書)

我們身為要求很高的user當然會把要求看到網頁不會卡卡的~

或是突然蹦出來這樣的突兀~!!

需求 使用者 目的 功能點
切換頁面不突兀 一般使用者 保持情緒穩定與方向感 router-view 外層 <Transition>
填表更有節奏 點單者 逐步完成、不被資訊淹沒 表單步驟 <Transition>
列表更好讀 祕書/收單者 新增/刪除時不跳動 <TransitionGroup> + FLIP
等待不焦慮 所有人 讀取時給「還在處理」的回饋 Loading + 減少布局抖動
尊重可近性 對動效敏感的使用者 避免眩暈/突兀動畫 prefers-reduced-motion 查詢

🪄 時序圖:新增訂單的視覺流程

我們可以看一下時序突來呈現整個程式運作的時間互動

https://ithelp.ithome.com.tw/upload/images/20251009/201210521SU2axcYmj.png


二、過場魔法的概念與技術

  • <Transition>單一元素/區塊的出入場魔法(常用於 v-ifrouter-view)。
  • <TransitionGroup>多元素的插入/移除/排序動畫(自帶 FLIP 位移魔法)。
  • 過場咒語的三階段:*-enter-from → *-enter-active → *-enter-to(離場則反向)。
  • 可利用「生命週期掛勾」自訂魔法動作:@before-enter@enter@after-leave
  • 路由過場:在 <RouterView> 外層加 <Transition>,就能實現頁面級轉場。
  • prefers-reduced-motion:系統層咒語,尊重對動畫敏感的使用者。

三、實作(不動後端)

今天我們不會動到後端的code~

以下程式碼僅為「施展過場魔法」,不會影響邏輯功能。
讓畫面「淡入、滑入、自然地轉換」。


1. 頁面切換過場(App.vue)

<template>
  <main class="page">
    <h1>飲料點單系統</h1>
    <nav style="display:flex; gap:8px; margin:12px 0;">
      <router-link to="/order" class="btn">點餐之塔</router-link>
      <router-link to="/summary" class="btn">結算之室</router-link>
    </nav>

    <RouterView v-slot="{ Component }">
      <Transition name="page" mode="out-in">
        <component :is="Component" />
      </Transition>
    </RouterView>
  </main>
</template>

<style>
.page-enter-from { opacity: 0; transform: translateY(6px) scale(0.98); }
.page-enter-active, .page-leave-active { transition: all .18s ease; }
.page-leave-to { opacity: 0; transform: translateY(-6px) scale(0.98); }

@media (prefers-reduced-motion: reduce) {
  .page-enter-active, .page-leave-active { transition-duration: 0s; }
}
</style>

CSS 語法與用途

語法 用途 魔法描述
.page-enter-from 進場初始狀態 畫面剛出現時透明且略低,像魔法陣正在升起。
.page-enter-active 動畫過程 控制動畫時間與速率。
.page-leave-to 離場結束狀態 畫面漸隱,往上漂浮消散。
transition: all .18s ease; 動畫時間 0.18 秒的柔和節奏。
@media (prefers-reduced-motion) 系統檢測 為動效敏感者關閉動畫。

2. 表單步驟過場(OrderForm.vue)

<template>
  <OptionGroup label="步驟 1:選擇飲料" :options="drinks" v-model="drink" required />

  <Transition name="step" appear>
    <div v-if="drink">
      <OptionGroup label="步驟 2:選擇甜度" :options="optSweetness" v-model="sweetness" required />
    </div>
  </Transition>

  <Transition name="step">
    <div v-if="drink && sweetness">
      <OptionGroup label="步驟 3:選擇冰量" :options="optIce" v-model="ice" required />
    </div>
  </Transition>

  <button :disabled="!canSubmit" class="submit" @click="addOrder">
    {{ canSubmit ? '送出' : '請完成所有必填' }}
  </button>
</template>

<style scoped>
.step-enter-from { opacity: 0; transform: translateY(6px); }
.step-enter-active, .step-leave-active { transition: all .16s ease; }
.step-leave-to { opacity: 0; transform: translateY(-6px); }

@media (prefers-reduced-motion: reduce) {
  .step-enter-active, .step-leave-active { transition-duration: 0s; }
}
</style>

CSS 語法與用途

語法 用途 魔法描述
.step-enter-from 進場起點 選項淡淡浮現,像召喚出的選單。
.step-enter-active 控制動畫過程 0.16 秒內完成柔順滑入。
.step-leave-to 消失階段 淡出並上升,如能量散去。
translateY() 位移效果 製造上下滑動感。
opacity 不透明度 讓過場自然柔和。

3. 列表插入/移除過場(OrderList.vue)

<template>
  <TransitionGroup name="list" tag="ul">
    <li v-for="(o, i) in orders" :key="o.id || i" class="order">
      <div class="row">
        <div class="col">
          <span class="idx">{{ i + 1 }}.</span>
          <span class="name">{{ o.name }}</span>
          <span class="pill">{{ o.drink }}</span>
          <span class="pill" :class="o.ice === '去冰' ? 'is-noice' : 'is-ice'">{{ o.ice }}</span>
          <span class="pill" :class="o.sweetness === '去糖' ? 'is-nosugar' : 'is-sugar'">{{ o.sweetness }}</span>
          <span v-if="o.note" class="note">備註:{{ o.note }}</span>
        </div>
        <div class="actions">
          <router-link v-if="o.id" class="btn btn-sm" :to="`/order/${o.id}`">詳情</router-link>
          <button class="btn btn-sm" @click="$emit('edit', { index: i, patch: o })">編輯</button>
          <button class="btn btn-sm del" @click="$emit('remove', i)">刪除</button>
        </div>
      </div>
    </li>
  </TransitionGroup>
</template>

<style scoped>
.list-enter-from, .list-leave-to { opacity: 0; transform: translateY(6px); }
.list-enter-active, .list-leave-active { transition: all .14s ease; }
.list-move { transition: transform .14s ease; }

@media (prefers-reduced-motion: reduce) {
  .list-enter-active, .list-leave-active, .list-move { transition-duration: 0s; }
}
</style>

CSS 語法與用途

語法 用途 魔法描述
.list-enter-from 新項目初始 元素剛生成時半透明、微下沉。
.list-enter-active 插入動畫 平滑浮上、淡入。
.list-leave-to 離場動畫 項目往下淡出,像被捲回卷軸。
.list-move 項目排序動畫 使用 FLIP 技術自動調整位置。

4. Loading 淡入效果(全域 style.css)

.loading-message {
  opacity: 0;
  animation: fadeIn .18s ease forwards;
}
@keyframes fadeIn { to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .loading-message { animation: none; opacity: 1; }
}

CSS 語法與用途

語法 用途 魔法描述
@keyframes fadeIn 定義動畫幀 從透明到顯現。
animation: fadeIn .18s ease forwards; 播放動畫 Loading 從無到有的漸入咒語。
forwards 保留終態 動畫完成後保持不透明。

四、魔法流轉圖(頁面 ↔ 區塊過場)

https://ithelp.ithome.com.tw/upload/images/20251009/20121052zLRuBKlCtg.png


五、最佳實踐(魔法守則)

下面是如果使用css動畫的一些提示: 可以參考一下

key 必穩定TransitionGroup 請使用固定 id,避免動畫錯位。
避免雙重過場:同一元素上不要套兩層動畫,容易衝突。
尊重可近性:支援 prefers-reduced-motion,讓每位使用者都能舒服體驗。
短而細的動畫:150–200ms 為最佳節奏,輕盈不拖泥帶水。
避免畫面跳動:預留空間避免 Layout Shift。
僅在可見時啟動:條件渲染節省效能。


六、魔法總表 ✨(今日 CSS 咒語總覽)

類別 適用範圍 主要屬性 動效時間 魔法效果 備註
.page-* 整頁切換 opacity, transform 0.18s 頁面淡入淡出 + 浮動 用於 <RouterView>
.step-* 表單步驟 opacity, translateY 0.16s 表單項目滑入滑出 用於 <Transition>
.list-* 訂單列表 opacity, transform 0.14s 插入/刪除平滑位移 用於 <TransitionGroup>
.list-move 列表重排 transform 0.14s FLIP 技術自動補位 Vue 自動套用
.loading-message 載入提示 opacity, animation 0.18s 淡入 Loading 支援 reduced motion

今天我們的程式碼
day18 github

七、小結(今日魔法成果)

今天,我們讓「飲料點單系統」不再只是能運作的程式,
而是一場「流動的魔法表演」。

  • 透過 <Transition>,畫面淡入淡出如施法。
  • <TransitionGroup> 讓項目增減自然、不跳動。
  • 支援系統偏好,尊重不同使用者體驗。

魔法師心得:

過場不是特效,而是「使用者與系統之間的節奏對話」。
一點流暢的過場,能讓操作更直覺、體驗更優雅。


其實前端工程師就是要學這麼多東西~
除了資料以外還有視覺效果處理的方式

另外能讓使用者體感更好的介面也是一大課題
接者我會把我想寫的或傳達的跟大家分享~

請大家繼續跟者大法師柯基完成最後的旅途吧~!!


上一篇
Day 17 : 多語系施法術:Vue i18n 靜態 + 後端動態字典完整實戰
下一篇
# Day 19 : 雙重傳送門的召喚術:Teleport + Modal + Toast 一次到位
系列文
需求至上的 Vue 魔法之旅27
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言