Try   HackMD

transition 元件

竹白記事本
Vue Transition|目錄

tags: Vue Transition 竹白的 Vue.js 學習筆記

transition 元件

Vue 提供了 transition 的封裝元件,在下列情形中,可以給任何元素和元件添加進入/離開的轉場效果:

  • 元素或元件初始渲染時
  • 元素或元件顯示/隱藏時(使用 v-ifv-show
  • 元素或元件切換時

先看一個簡單的基本範例:

<button v-on:click="show = !show">Toggle</button>
<transition>
  <div class="box" v-if="show">2</div>
</transition>
data: {
  show: true,
},
.v-enter, .v-leave-to {
  opacity: 0;
}
.v-leave, .v-enter-to {
  opacity: 1;
}

.v-enter-active,
.v-leave-active {
  transition: opacity 1s;
}

當我們使用 transition 元件將元素包住,Vue 會做以下處理:

  1. 自動偵測目標元素是否應用 CSS transition/animation 如果是,在恰當的時機添加/刪除 CSS 類別名稱。
  2. 如果 transition 元件提供了 JavaScript 鉤子函式,這些鉤子函式將在恰當的時機被呼叫。
  3. 如果沒有找到 JavaScript 鉤子並且也沒有檢測到 CSS transition/animation,DOM 操作 (插入/刪除) 在下一幀中立即執行。

CSS 轉場的類別名稱

transition 元件共提供了,六種類別名稱提供切換。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

進場:

  • v-enter:定義進場的開始狀態。
    • 在元素被插入之前生效,插入之後的下一幀被移除
  • v-enter-active:定義進場生效時的狀態,在整個進場的階段中應用。
    • 在元素被插入之前生效,在 transition/animation 完成之後移除
    • 可用來定義進場的過程時間,延遲和曲線函數
  • v-enter-to2.1.8版及以上 定義進場的結束狀態。
    • 在元素被插入之後下一幀生效(與此同時 v-enter 被移除),在 transition/animation 完成之後移除

離場:

  • v-leave:定義離場的開始狀態。
    • 在離場被觸發時立刻生效,下一幀被移除
  • v-leave-active:定義離場生效時的狀態,在整個離場的階段中應用。
    • 在離場被觸發時立刻生效,在 transition/animation 完成之後移除
    • 這個類可以被用來定義離場的過程時間,延遲和曲線函數
  • v-leave-to2.1.8版及以上 定義離場的結束狀態。
    • 在離開轉場被觸發之後下一幀生效(與此同時 v-leave 被移除),在 transition/animation 完成之後移除

通常會設定 v-enterv-leave-active 相同的效果、v-leavev-enter-to 相同的效果,達到同尾相接形成一個循環,而 v-enter-tov-leave-to 會用來設定轉場時間或動畫。

enter-to 預設 opacity: 1transform: none,所以不一定要設定。

1. CSS transition

transition 元件預設使用上述 v- 前綴的類別名稱。請參考一開始基本範例。

因為不可能只用一種動態效果,因此使用自訂義的前綴,需要加上 name 特性,舉例來說,<transition name="fade">,套用的那麼類別名稱的前綴就會是 fade-enter

<button v-on:click="show = !show">
  Toggle
</button>
<transition name="fade">
  <div class="box" v-if="show"></div>
</transition>

設定一個進場由透明度 0 變 1 並由右測 100px 處滑入,並且進場、離場分別設定不同的曲線函數:

.fade-enter,
.fade-leave-to {
  opacity: 0;
  transform: translateX(100px);
}
.fade-leave, .fade-enter-to {
  opacity: 1;
}

.fade-enter-active {
  transition: all 0.3s ease;
}
.fade-leave-active {
  transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}

再舉一個例子,由下往上進場,由右出場:

.fade-enter {
  opacity: 0;
  transform: translateY(100%);
}

.fade-enter-to, .fade-leave {
  opacity: 1;
}

.fade-leave-to {
  opacity: 0;
  transform: translateX(100%);
}

.fade-enter-active,.fade-leave-active {
  transition: all 0.8s ease;
}

2. CSS animation

CSS animation 用法同 CSS transition,區別是在動畫中 v-enter 類名在節點插入 DOM 後不會立即刪除,而是在 animationend 事件觸發時刪除。

.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.5);
  }
  100% {
    transform: scale(1);
  }
}

使用自訂義類別名稱

我們可以通過以下 transition 元件特性來使用自訂義類別名稱:

  • enter-class
  • enter-active-class
  • enter-to-class 2.1.8+
  • leave-class
  • leave-active-class
  • leave-to-class 2.1.8+

他們的優先級高於普通的類別名稱。

舉個簡單得範例,來說明使用方式:

.opacity-0 {
  opacity: 0;
}

.trs-time-3 {
  transition-duration: 3s;
}
<transition
  enter-class="opacity-0"
  leave-to-class="opacity-0"
  enter-active-class="trs-time-3"
  leave-active-class="trs-time-3"
>
  <div class="box" v-if="show"></div>
</transition>

1. 第三方 CSS 動畫庫

自訂義類別名稱,對於套用第三方 CSS 動畫庫結合非常方便。

舉例來說,使用 Animate.css 的動畫效果:

<button v-on:click="show = !show">
  Toggle
</button>
<transition
  enter-active-class="animated tada"
  leave-active-class="animated bounceOutRight"
>
  <div class="box" v-if="show"></div>
</transition>
<transition
  enter-active-class="animated fadeInUp"
  leave-active-class="animated flipInY"
>
  <div class="box" v-if="show"></div>
</transition>

或者是 magic.css

<button v-on:click="show = !show">
  Toggle
</button>
<transition
  enter-active-class="magictime foolishIn"
  leave-active-class="magictime tinDownOut"
>
  <div class="box" v-if="show"></div>
</transition>

轉場時間

1. 同時使用 transition/animation

Vue 為了知道轉場的完成,必須設置相應的事件監聽器。它可以是 transitionendanimationend,這取決於給元素應用的 CSS 規則。如果你使用其中任何一種,Vue 能自動識別類型並設置監聽。

但有時候會遇到需要同時設置的情況,但兩邊的完成時間不一致,這時候就需要手動設置 transitionendanimationend 來明確告知 Vue 要監聽的類型。

舉例來說,假設你分別使用自訂義的類別名稱和 Animate.css :

.fade-enter,.fade-leave-to {
  opacity: 0;
}

.fade-enter-to, .fade-leave {
  opacity: 1;
}

.fade-enter-active,.fade-leave-active {
  transition: opacity 3s;
}
<transition
  name="fade"
  type="transition"
  enter-active-class="animated swing fade-enter-active"
  leave-active-class="animated bounce fade-leave-active"
>
  <div class="box" v-if="show"></div>
</transition>

這裡要注意,使用自訂義類別名稱優先度大於普通的類別名稱,所以fade-enter-activefade-leave-active 記得要補上。

Animate.css 預設動畫時間為 1s,而我們設置的 transition 時間為 3s,Animate.css 的動畫很外就觸發完成了,而轉場還沒結束。在很多情況下,Vue 可以自動得出轉場效果的完成時機,但還是有可能出現例外。

為了避免出現例外,你就需要手動設定 type="transition"transition 的時間為準。反之動畫時間大於轉場就以動畫時間為準。

2. 顯性的轉場持續時間

上面已經提過了,在很多情況下,Vue 可以自動得出轉場效果的完成時機。預設情況下,Vue 會等待其在轉場效果的根元素的第一個 transitionendanimationend 事件。

但在某些情況下,還可以自定義整個動態效果總時間長,使用的是 duration 特性搭配 v-bind

舉例來說,總時常為 5s:

<transition :duration="5000">...</transition>

也可以分別設定進入和移除持續時間:

<transition :duration="{ enter: 500, leave: 800 }">...</transition>

這是一個 transition 需要 5秒,但總轉場時間強制設為 1秒的範例:

初始渲染的轉場

透過設定 appear 特性,設置節點在初始渲染的轉場。

<transition appear>
  <!-- ... -->
</transition>

CodePen,載入畫面時,會有進場效果。

appear 預設使用進場的類別,如果要與進場套用不同的動畫效果,需要使用自定義的類別名稱:

<transition
  appear
  appear-class="custom-appear-class"
  appear-to-class="custom-appear-to-class" (2.1.8+)
  appear-active-class="custom-appear-active-class"
>
  <!-- ... -->
</transition>