Vue 封裝好的 transition 元件提供開發者在插入、更新、移除 DOM 時,添加動畫轉場的效果。它提供三種應用方式:
使用條件
- 使用 v-if
- 使用 v-show
- 動態元件 (Dynamic Components),如使用 :is,透過字串變數進行元件切換
- 元件的根節點(Component Root Nodes)
方法1 - CSS 轉場 & CSS 動畫
預設的轉場類名
使用 <transition> 時,Vue 會在特定時間點將對應的 class 加到元素中,然後再移除,產生進入和離開的漸變效果。
- v-enter
 進入轉場開始的狀態。在元素插入前生效,在元素被插入後的下一幀移除
- v-enter-active
 進入轉場過程的狀態。在整個進入轉場的階段中應用,在轉場完成之後移除。在這裡可以定義轉場的過程時間,延遲。如:- transition: opacity .5s
- v-enter-to
 進入轉場結束的狀態。在元素被插入之後下一幀生效(與此同時 v-enter 被移除),在轉場完成之後移除 (2.1.8版以上)
- v-leave
 離開轉場的開始狀態。在離開轉場被觸發時立即生效,下一幀被移除
- v-leave-active
 離開轉場生效時的狀態。在整個離開轉場的階段中應用,在轉場完成之後移除。在這裡可以定義轉場的過程時間,延遲。如:- transition: opacity .5s
- v-leave-to
 離開轉場結束的狀態。在- v-leave被觸發之後下一幀生效(與此同時 v-leave 被移除),在轉場完成之後移除 (2.1.8版以上)

來源: Vue 官方文件
若無自行定義類別的前綴詞,預設是 v- (如上)。若有自行定義需求,則可以在 <transition> 標籤添加 name 屬性,並且將預設類別 v- 的 v 改為自定義名稱。
CSS 轉場
| 1 | <div id="demo"> | 
| 1 | new Vue({ | 
| 1 | .fade-enter-active, .fade-leave-active { | 
See the Pen RzeYmR by Dylan (@dylan_demo) on CodePen.
流程敘述
- 第一次點擊按鈕,變數 show被更改為false,此時元素移除,同時觸發leave→leave-active→leave-to
- 第二次點擊按鈕,變數 show被更改為true,此時元素插入,同時觸發enter→enter-active→enter-to
另外 v-if 也可以改為 v-show,後者並不會移除元素,而是以 display: block 和 display: none 做切換。
CSS 動畫
使用 CSS animation 和 CSS transition 基本上沒有太大差異,區別是在動畫中 v-enter 在節點插入 DOM 後不會立即刪除,而是在 animationend 事件觸發時刪除。
| 1 | <div id="demo"> | 
| 1 | new Vue({ | 
| 1 | .bounce-enter-active { | 
See the Pen qzJMzB by Dylan (@dylan_demo) on CodePen.
方法2 - 搭配第三方動畫套件 (Animate.css)
客製化的方式除了方法一之外,Vue 也提供了另外一種方式。我們可以直接在 <transition> 標籤內插入屬性,值則為第三方庫寫好的 Class Name。以下範例使用 Animate.css 動畫庫做範例。
預設的轉場屬性
我們可以通過以下屬性來自定義轉場類名,時間點可以對應到上面提到的預設的轉場類名:
- enter-class
- enter-active-class
- enter-to-class(2.1.8+)
- leave-class
- leave-active-class
- leave-to-class(2.1.8+)
範例
| 1 | <div id="demo"> | 
| 1 | new Vue({ | 
See the Pen XLxPLG by Dylan (@dylan_demo) on CodePen.
方法3 - JavaScript 鉤子函式
另一種方法則是在 <transition> 元素行內綁定鉤子,可以搭配 CSS 轉場和 CSS 動畫使用,也可單獨使用。
預設鉤子
- beforeEnter(el)
 進入轉場/動畫前啟動
- enter(el, callback)
 進入轉場/動畫之元素插入時啟動。- done callback則在結束時呼叫,可傳可不傳。
 與- 方法2所對應的時間點為- enter-class
- afterEnter(el)
 進入轉場/動畫時啟動。
 與- 方法2所對應的時間點為- enter-to-class
- enterCancelled(el)
 在未完成進入轉場/動畫時取消動作。
- beforeLeave(el)
 離開轉場/動畫前啟動
- leave(el, callback)
 離開轉場/動畫之元素插入時啟動。- done callback則在結束時呼叫,可傳可不傳。
 與- 方法2所對應的時間點為- leave-class
- afterLeave(el)
 離開轉場/動畫時啟動。
- leaveCancelled(el)
 在未完成離開轉場/動畫時取消動作。
 與- 方法2所對應的時間點為- leave-to-class
補充:當只用JavaScript 轉場的時候,在enter和leave中必須使用done進行callback。否則,它們將被同步呼叫,轉場會立即完成。
補充:推薦對於僅使用 JavaScript 轉場的元素添加
:css="false",Vue 會跳過 CSS 的檢測。這也可以避免過渡過程中 CSS 的影響。
範例
一個使用 Velocity.js 函式庫的簡單例子:
| 1 | <div id="demo"> | 
| 1 | new Vue({ | 
See the Pen YoJJKq by Dylan (@dylan_demo) on CodePen.
兩個元素的過場動畫
透過 v-if 同時讓兩個元素進行過場。
| 1 | <div id="demo"> | 

我們會發現,在動畫執行階段兩個元素會在同個時間交集,造成空間互相擠壓的問題。這並不是我們想要的結果。
而 Vue 的 transition 元件提供了一個解法,我們可以為 transition 標籤加上另一個屬性 mode。 
- in-out: 新的元素先執行- enter,待完成後舊元素才執行- leave
- out-in:舊元素先執行- leave,待完成後新元素才執行- enter(一般符合預期的狀況)
稍作修改
| 1 | <transition name="fade" mode="out-in"> | 

另外有一點需要特別注意,剛剛的例子使用的是兩個不同元素(h1及h2),是可以正常執行的,但是如果兩個元素是相同的就會出現一些問題。
| 1 | <div id="demo"> | 

我們可以為 transition 標籤加上 key,來解決這個問題,key 內的值需要是唯一值,即每個元素的值不可重複,如此 Vue 才能判斷它為不同的元素,進而正常執行過場。
| 1 | <div id="demo"> | 
See the Pen ydRRPr by Dylan (@dylan_demo) on CodePen.
多個元素的過場
前面的例子都是使用 v-if 來做過場效果,最多只有兩個元素,如果使用 v-for 產生的大量元素就必須使用 transition-group 元件。
transition-group 在編譯後預設會被轉換成 span 標籤,由這個標籤包住所有 v-for 渲染出來的元素。例如:
| 1 | <transition-group name="fade"> | 
編譯結果為:
| 1 | <span> | 
我們可以透過 tag 屬性將預設標籤改掉
| 1 | <transition-group name="fade" tag="div"> | 
編譯結果為:
| 1 | <div> | 
注意:和
transition元件一樣,在transition-group的元素也必須為它加上key
使用 bootstrap 卡片元件來製作一個簡易的新增刪除功能的表單,並且使用 <transition-group> 加上動畫效果吧。
| 1 | <div id="demo"> | 
| 1 | let app = new Vue({ | 
See the Pen Rzevvx by Dylan (@dylan_demo) on CodePen.
重複利用動畫效果
可以使用元件及插槽(Slot)封裝你精心設計的動畫效果,下個專案可以重複利用,這邊使用上面卡片的範例來做。
| 1 | <div id="demo"> | 
| 1 | // 區域元件 (二擇一) | 
See the Pen MMzGYp by Dylan (@dylan_demo) on CodePen.
參考資料
Vue 官方文件
Vue.js (14) - 過場效果及動畫
Vue.js: 樣式與漸變 Transitions
Vue.js: 動畫 Animations
Vue.js: 進階過渡效果