Transition,官方文件介紹六個內建的組件,
在實用範例裡頭有出現過摟,做動畫的時候需要他~
不知道還有沒有其他的應用?
Vue 提供了兩個內建組件,可以幫助在狀態變更時進行過渡和動畫處理:
<Transition>
:用於在元素或組件進入和離開 DOM 時應用動畫。這部分內容在本頁面中涵蓋。<TransitionGroup>
:用於在元素或組件插入、移除或在 v-for
列表中移動時應用動畫。這部分內容在下一篇EP中涵蓋。除了這兩個組件,我們還可以使用其他技術在 Vue 中應用動畫,例如切換 CSS 類或通過樣式綁定進行狀態驅動的動畫。這些額外技術在《動畫技術》章節中進行說明。
<Transition>
組件<Transition>
是一個內建組件:這意味著它可以在任何組件的模板中使用,而無需註冊。它可以用於在傳遞給它的元素或組件上應用進入和離開的動畫,這些元素或組件通過其預設插槽傳遞。進入或離開的觸發可以通過以下方式之一:
v-if
進行條件渲染v-show
進行條件顯示<component>
特殊元素進行動態組件切換key
屬性以下是最基本用法的示例:
<button @click="show = !show">Toggle</button>
<Transition>
<p v-if="show">hello</p>
</Transition>
/* 我們將在接下來解釋這些類的作用! */
.v-enter-active,
.v-leave-active {
transition: opacity 0.5s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
<Transition>
只支持單個元素或組件作為其插槽內容。如果內容是一個組件,則該組件也必須只有一個根元素。
當 <Transition>
組件中的元素被插入或移除時,會發生以下情況:
有六個類別用於進入/離開過渡。
v-enter-active
和 v-leave-active
使我們能夠為進入/離開過渡指定不同的緩動曲線,接下來的部分將會提供範例。
可以通過 name
屬性來給過渡效果命名:
<template>
<Transition name="fade">
...
</Transition>
</template>
對於命名過渡效果,它的過渡類名將以指定的名稱為前綴,而不是 v
。例如,對於上述過渡效果,應用的類名將是 fade-enter-active
而不是 v-enter-active
。 fade
過渡效果的 CSS 應如下所示:
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
這樣設置後,在元素進入和離開時會有漸隱漸現的效果。
<Transition>
元件最常與原生的 CSS 過渡效果結合使用,如上面的基本範例所示。transition
CSS 屬性是一個簡寫,允許我們指定過渡效果的多個方面,包括需要動畫化的屬性、過渡的持續時間和緩動曲線。
這裡是一個更進階的範例,過渡多個屬性,並為進入和離開設置不同的持續時間和緩動曲線:
<template>
<Transition name="slide-fade">
<p v-if="show">hello</p>
</Transition>
</template>
/*
進入和離開動畫可以使用不同的持續時間和時間函數。
*/
.slide-fade-enter-active {
transition: all 0.3s ease-out;
}
.slide-fade-leave-active {
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter-from,
.slide-fade-leave-to {
transform: translateX(20px);
opacity: 0;
}
在這個範例中,當元素進入時,它會在 0.3 秒內使用 ease-out
緩動曲線從右側滑入並逐漸顯現;而當元素離開時,它會在 0.8 秒內使用自定義的 cubic-bezier
緩動曲線滑出並逐漸隱藏。這樣的設置使得過渡效果更加豐富和細緻。
原生 CSS 動畫的應用方式與 CSS 過渡效果相同,不同之處在於 *-enter-from
不會在元素插入後立即被移除,而是在 animationend
事件後才移除。
對於大多數 CSS 動畫,我們可以簡單地將它們聲明在 *-enter-active
和 *-leave-active
類中。以下是一個範例:
<template>
<Transition name="bounce">
<p v-if="show" style="text-align: center;">
Hello here is some bouncy text!
</p>
</Transition>
</template>
.bounce-enter-active {
animation: bounce-in 0.5s;
}
.bounce-leave-active {
animation: bounce-in 0.5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.25);
}
100% {
transform: scale(1);
}
}
在這個範例中,當元素進入時會執行 bounce-in
動畫,動畫持續 0.5 秒;當元素離開時,則執行相同動畫的反向過程。這使得文本在顯示和隱藏時有彈跳的效果。
你也可以通過向 <Transition>
傳遞以下屬性來指定自訂過渡類名:
enter-from-class
enter-active-class
enter-to-class
leave-from-class
leave-active-class
leave-to-class
這些屬性會覆蓋傳統的類名。這在你希望將 Vue 的過渡系統與現有的 CSS 動畫庫(如 Animate.css)結合使用時特別有用:
<template>
<!-- 假設 Animate.css 已經被包含在頁面中 -->
<Transition
name="custom-classes"
enter-active-class="animate__animated animate__tada"
leave-active-class="animate__animated animate__bounceOutRight"
>
<p v-if="show">hello</p>
</Transition>
</template>
在這個範例中,當元素進入時會應用 animate__tada
動畫效果,而當元素離開時會應用 animate__bounceOutRight
動畫效果。這種方法使你可以靈活地使用任何 CSS 動畫庫來增強過渡效果。
Vue 需要附加事件監聽器來判斷過渡何時結束。這可能是 transitionend
或 animationend
,取決於應用的 CSS 規則類型。如果你只使用其中之一,Vue 可以自動檢測正確的類型。
但是,有時你可能希望在同一個元素上同時使用兩者,例如,通過 Vue 觸發的 CSS 動畫,與懸停時的 CSS 過渡效果。在這些情況下,你需要通過 type
屬性明確指定 Vue 應關注的類型,值為 animation
或 transition
:
<template>
<Transition type="animation">...</Transition>
</template>
雖然過渡類名只應用於 <Transition>
的直接子元素,但我們可以使用嵌套的 CSS 選擇器來過渡嵌套元素:
<template>
<Transition name="nested">
<div v-if="show" class="outer">
<div class="inner">
Hello
</div>
</div>
</Transition>
</template>
/* 針對嵌套元素的規則 */
.nested-enter-active .inner,
.nested-leave-active .inner {
transition: all 0.3s ease-in-out;
}
.nested-enter-from .inner,
.nested-leave-to .inner {
transform: translateX(30px);
opacity: 0;
}
/* 延遲嵌套元素進入以實現分段效果 */
.nested-enter-active .inner {
transition-delay: 0.25s;
}
不過,這會帶來一個小問題。默認情況下,<Transition>
組件嘗試通過監聽根過渡元素上的第一個 transitionend
或 animationend
事件來自動判斷過渡何時完成。對於嵌套過渡,理想行為應該是等待所有內部元素的過渡完成。
在這種情況下,你可以在 <Transition>
組件上使用 duration
屬性來指定明確的過渡持續時間(以毫秒為單位)。總持續時間應與嵌套元素的延遲加過渡持續時間相匹配:
<template>
<Transition :duration="550">...</Transition>
</template>
如果需要,你也可以使用物件為進入和離開的持續時間指定不同的值:
<template>
<Transition :duration="{ enter: 500, leave: 800 }">...</Transition>
</template>
你可能會注意到上面顯示的動畫主要使用了像 transform
和 opacity
這樣的屬性。這些屬性之所以在動畫中高效,原因如下:
相比之下,像 height
或 margin
這樣的屬性會觸發 CSS 佈局,因此動畫化的成本更高,應謹慎使用。
你可以透過在 <Transition>
組件上監聽事件來使用 JavaScript 鉤子來連接過渡過程:
<Transition
@before-enter="onBeforeEnter"
@enter="onEnter"
@after-enter="onAfterEnter"
@enter-cancelled="onEnterCancelled
@before-leave="onBeforeLeave"
@leave="onLeave"
@after-leave="onAfterLeave"
@leave-cancelled="onLeaveCancelled"
>
<!-- ... -->
</Transition>
以下是各個鉤子的功能說明:
// 在元素插入 DOM 之前調用。
// 使用這個來設置元素的 "enter-from" 狀態
function onBeforeEnter(el) {}
// 在元素插入後的一幀調用。
// 使用這個來開始進入動畫。
function onEnter(el, done) {
// 調用 done 回調來指示過渡結束
// 如果與 CSS 一起使用則為可選
done()
}
// 當進入過渡完成時調用。
function onAfterEnter(el) {}
// 當進入過渡在完成之前被取消時調用。
function onEnterCancelled(el) {}
// 在離開鉤子之前調用。
// 大多數情況下,你應該只使用離開鉤子
function onBeforeLeave(el) {}
// 當離開過渡開始時調用。
// 使用這個來開始離開動畫。
function onLeave(el, done) {
// 調用 done 回調來指示過渡結束
// 如果與 CSS 一起使用則為可選
done()
}
// 當離開過渡完成並且
// 元素已被移除自 DOM 時調用。
function onAfterLeave(el) {}
// 只有在 v-show 過渡中可用
function onLeaveCancelled(el) {}
這些鉤子可以與 CSS 過渡/動畫結合使用,或者單獨使用。
在使用僅 JavaScript 的過渡時,通常建議添加 :css="false"
屬性。這明確告訴 Vue 跳過自動 CSS 過渡檢測。這樣不僅性能稍好,還可以防止 CSS 規則意外干擾過渡:
<template>
<Transition
...
:css="false"
>
...
</Transition>
</template>
使用 :css="false"
時,我們也完全負責控制過渡結束的時間。在這種情況下,done
回調對於 @enter
和 @leave
鉤子是必需的。否則,鉤子將會同步調用,過渡將立即結束。
以下是一個使用 GSAP 庫來執行動畫的示例。當然,你也可以使用其他任何動畫庫,例如 Anime.js 或 Motion One。
過渡可以通過 Vue 的組件系統重用。要創建可重用的過渡,我們可以創建一個組件來包裝 <Transition>
組件並傳遞插槽內容:
<!-- MyTransition.vue -->
<script>
// JavaScript 鉤子邏輯...
</script>
<template>
<!-- 包裝內建的 Transition 組件 -->
<Transition
name="my-transition"
@enter="onEnter"
@leave="onLeave">
<slot></slot> <!-- 傳遞插槽內容 -->
</Transition>
</template>
<style>
/*
必要的 CSS...
注意:避免在這裡使用 <style scoped>,因為它
不適用於插槽內容。
*/
</style>
現在,MyTransition
可以像內建版本一樣導入和使用:
<template>
<MyTransition>
<div v-if="show">Hello</div>
</MyTransition>
</template>
如果您想在節點的初始渲染時應用過渡,可以添加 appear
屬性:
<template>
<Transition appear>
...
</Transition>
</template>
這樣可以確保在組件首次出現時也能應用過渡效果,增強用戶體驗。使用 appear
屬性,Vue 將會在元素首次插入到 DOM 中時觸發過渡,而不僅僅是在狀態變化時。
除了使用 v-if
或 v-show
切換元素外,我們還可以使用 v-if
、v-else
和 v-else-if
之間進行過渡,只要確保在任何時刻只有一個元素被顯示即可:
<template>
<Transition>
<button v-if="docState === 'saved'">編輯</button>
<button v-else-if="docState === 'edited'">保存</button>
<button v-else-if="docState === 'editing'">取消</button>
</Transition>
</template>
這種方法允許我們在不同狀態之間進行平滑過渡,從而改善用戶界面的互動性和可用性。當用戶進行操作時,過渡效果能夠讓介面變得更流暢且具吸引力。
在前面的示例中,進入和離開的元素同時被動畫化,因此我們必須將它們設置為 position: absolute
,以避免在兩個元素同時存在於 DOM 中時出現佈局問題。
然而,在某些情況下,這並不是一個選項,或者根本不是我們希望的行為。我們可能希望離開的元素先被動畫化,而在離開動畫完成之前,不再插入進入的元素。手動協調這種動畫會非常複雜,幸運的是,我們可以通過將模式屬性傳遞給 <Transition>
來啟用此行為:
<template>
<Transition mode="out-in">
...
</Transition>
</template>
可以在上一個範例中,使用 mode="out-in"
:
此外,<Transition>
也支持 mode="in-out"
,儘管使用頻率較低。
<Transition>
也可以用於包裹動態元件:
<template>
<Transition name="fade" mode="out-in">
<component :is="activeComponent"></component>
</Transition>
</template>
在這個例子中,<Transition>
被用來包裹一個動態元件,這樣在切換不同元件時就可以應用過渡效果。這使得用戶在不同元件之間的轉換時,體驗到更流暢的動畫效果。
這樣的用法特別適合需要頻繁切換的情境,例如在單頁應用(SPA)中切換不同的視圖或組件。利用 Vue 的過渡系統,可以輕鬆地實現動態過渡效果,提升用戶體驗。
<Transition>
的屬性,例如 name
,也可以是動態的!這使我們能根據狀態變化動態應用不同的過渡效果:
<template>
<Transition :name="transitionName">
<!-- ... -->
</Transition>
</template>
這在你使用 Vue 的過渡類別約定定義了 CSS 過渡或動畫時非常有用,特別是當你想在它們之間切換時。
你也可以根據元件的當前狀態在 JavaScript 過渡鉤子中應用不同的行為。最終,創建動態過渡的最佳方式是通過可重用的過渡元件,這些元件接受屬性以改變所使用的過渡類型。雖然這聽起來可能有些老套,但實際上唯一的限制就是你的想像力。
有時你需要強制重新渲染一個 DOM 元素,才能讓過渡發生。
以這個計數器元件為例:
<script setup>
import { ref } from 'vue';
const count = ref(0);
setInterval(() => count.value++, 1000);
</script>
<template>
<Transition>
<span :key="count">{{ count }}</span>
</Transition>
</template>
如果我們排除了 key
屬性,則只有文本節點會被更新,因此不會發生過渡。然而,有了 key
屬性,Vue 知道每當 count
改變時,應該創建一個新的 span
元素,從而使 Transition 組件在兩個不同的元素之間進行過渡。
相關資料 <Transition>
API reference
沒想到這內建的組件Transition資料這麼多 Orz....
越來越覺得前端的學好真的頗難 www
繼續努力~學習的過程真有趣