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: 進階過渡效果