通過Vue.js 的過渡系統,你可以輕鬆的為DOM 節點被插入/移除的過程添加過渡動畫效果。 Vue 將會在適當的時機添加/移除CSS 類名來觸發CSS3 過渡/動畫效果,你也可以提供相應的JavaScript 鉤子函數在過渡過程中執行自定義的DOM 操作。
以v-transition="my-transition" 這個指令為例,當帶有這個指令的DOM 節點被插入或移除時,Vue 將會:
用my-transition 這個ID 去查找是否有註冊過的JavaScript 鉤子對象。這個對象可以是由Vue.transition(id, hooks) 全局註冊,或是通過transitions 選項定義在當前的組件內部。如果找到此對象,則會在過渡動畫不同的階段調用相應的鉤子。
自動探測目標元素是否應用了CSS 過渡效果或者動畫效果,並在適當的時機添加/移除CSS 類名。
如果沒有提供JavaScript 鉤子函數,也沒有檢測到相應的CSS 過渡/動畫效果,DOM 的插入/移除會在下一幀立即執行。
所有的Vue.js 過渡效果只有在該DOM 操作是通過Vue.js 觸發時才會生效。觸發的方式可以是通過內置指令,比如v-if,或是通過Vue 實例的方法,比如vm.$appendTo()。
CSS 過渡效果
一個典型的CSS 過渡效果定義如下:
<div v-if="show" v-transition="expand">hello</div>
你還需要定義.expand-transition, .expand-enter 和.expand-leave 三個CSS 類:
.expand-transition { transition: all .3s ease; height: 30px; padding: 10px; background-color: #eee; overflow: hidden;}.expand-enter, .expand-leave { height: 0; padding: 0 10px; opacity: 0;}同時,你也可以提供JavaScript 鉤子:
Vue.transition('expand', { beforeEnter: function (el) { el.textContent = 'beforeEnter' }, enter: function (el) { el.textContent = 'enter' }, afterEnter: function (el) { el.textContent = 'afterEnter' }, enterCancelled: function (el) { // handle cancellation },` beforeLeave: function (el) { el.textContent = 'beforeLeave' }, leave: function (el) { el.textContent = 'leave' }, afterLeave: function (el) { el.textContent = 'afterLeave' }, leaveCancelled: function (el) { // handle cancellation }})結果
這裡使用的CSS 類名由v-transition 指令的值所決定。以v-transition="fade" 為例,CSS 類.fade-transition 將會一直存在,而.fade-enter 和.fade-leave 將會在合適的時機自動被添加或移除。當v-transition 指令沒有提供值的時候,所使用的CSS 類名將會是默認的.v-transition, .v-enter 和.v-leave。
當show 屬性變化時,Vue 會依據其當前的值來插入/移除<div> 元素,並在合適的時機添加/移除對應的CSS 類,具體如下:
當show 變為false 時,Vue 將會:
1.調用beforeLeave 鉤子;
2.在元素上應用CSS 類.v-leave 來觸發過渡效果;
3.調用leave 鉤子;
4.等待過渡效果執行完畢; (監聽transitionend 事件)
5.從DOM 中移除元素並且移除CSS 類.v-leave。
6.調用afterLeave 鉤子。
當show 為true 時,Vue 將會:
1.調用beforeEnter 鉤子;
2.在元素上應用CSS 類.v-enter;
3.將元素插入DOM;
4.調用enter 鉤子;
5.應用.v-enter 類, 然後強制CSS 佈局以保證.v-enter 生效;最後移除.v-enter 來觸發元素過渡到原本的狀態。
6.等待過渡效果執行完畢;
7.調用afterEnter 鉤子。
此外,如果一個正在執行進入的過渡效果的元素在過渡還未完成之前就被移除,則enterCancelled 鉤子將會被執行。這個鉤子可以用於清理工作,比如移除在enter 時創建的計時器。對於正在離開過渡中又被重新插入的元素同理。
上述所有的鉤子函數執行時,其this 都指向相應的Vue 實例。如果一個元素本身是一個Vue 實例的根節點,則此實例將被應用為this;否則this 指向該過渡指令所屬的實例。
最後,enter 與leave 鉤子函數可以接受可選的第二個參數:一個回調函數。當你的函數簽名中含有第二個參數時,即表示你期望使用此回調來顯式地完成整個過渡過程,而不是依賴Vue 去自動檢測CSS 過渡的transitionend 事件。比如:
enter: function (el) { // 無第二個參數// 過渡效果的結束由CSS 過渡結束事件來決定}VS
enter: function (el, done) { // 有第二個參數// 過渡效果結束必須由手動調用`done` 來決定}當多個元素同時執行過渡效果時,Vue.js 會進行批量處理以保證只觸發一次強制佈局。
CSS 動畫
CSS 動畫通過與CSS 過渡效果一樣的方式進行調用,區別就是動畫中.v-enter 類並不會在節點插入DOM 後馬上移除,而是在animationend 事件觸發時移除。
示例: (省略了兼容性前綴)
<span v-show="show" v-transition="bounce">Look at me!</span>
.bounce-enter { animation: bounce-in .5s;}.bounce-leave { animation: bounce-out .5s;}@keyframes bounce-in { 0% { transform: scale(0); } 50% { transform: scale(1.5); } 100% { transform: scale(1); }}@keyframes bounce-out { 0% { transform: scale(1); } 50% { transform: scale(1.5); } 100% { transform: scale(0); }}結果
純JavaScript 過渡效果
你也可以只使用JavaScript 鉤子,不定義任何CSS 過渡規則。當只使用JavaScript 鉤子時,enter 和leave 鉤子必須使用done 回調,否則它們將會被同步調用,過渡將立即結束。下面的示例中我們使用jQuery 來註冊一個自定義的JavaScript 過渡效果:
Vue.transition('fade', { enter: function (el, done) { // 此時元素已被插入DOM // 動畫完成時調用done 回調$(el) .css('opacity', 0) .animate({ opacity: 1 }, 1000, done) }, enterCancelled: function (el) { $(el).stop() }, leave: function (el, done) { // 與enter 鉤子同理$(el).animate({ opacity: 0 }, 1000, done) }, leaveCancelled: function (el) { $(el).stop() }})定義此過渡之後,你就可以通過給v-transition 指定對應的ID 來調用它:
<p v-transition="fade"></p>
如果一個只使用JavaScript 過渡效果的元素恰巧也受到其它CSS 過渡/動畫規則的影響,這可能會對Vue 的CSS 過渡檢測機制產生干擾。碰到這樣的狀況時,你可以通過給你的鉤子對象添加css: false 來禁止CSS 檢測。
漸進過渡效果
當同時使用v-transition 和v-repeat 時,我們可以為列表元素添加漸進的過渡效果,你只需要為你的過渡元素加上stagger, enter-stagger 或者leave-stagger 特性(以毫秒為單位):
<div v-repeat="list" v-transition stagger="100"></div>
或者你也可以提供stagger, enterStagger 或eaveStagger 鉤子來進行更細粒度的控制:
Vue.transition('stagger', { stagger: function (index) { // 為每個過渡元素增加50ms 的延遲, // 但是最大延遲為300ms return Math.min(300, index * 50) }})示例:
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。