Vue.js 教程
本章節(jié)我們主要討論 Vue.js 的過渡效果與動畫效果。
Vue 在插入、更新或者移除 DOM 時,提供多種不同方式的應(yīng)用過渡效果。
Vue 提供了內(nèi)置的過渡封裝組件,該組件用于包裹要實(shí)現(xiàn)過渡效果的組件。
<transition name = "nameoftransition"> <div></div> </transition>
我們可以通過以下實(shí)例來理解 Vue 的過渡是如何實(shí)現(xiàn)的:
實(shí)例中通過點(diǎn)擊 "點(diǎn)我" 按鈕將變量 show 的值從 true 變?yōu)?false。如果為 true 顯示子元素 p 標(biāo)簽的內(nèi)容。
下面這段代碼展示了 transition 標(biāo)簽包裹了 p 標(biāo)簽:
<transition name = "fade"> <p v-show = "show" v-bind:style = "styleobj">動畫實(shí)例</p> </transition>
過渡其實(shí)就是一個淡入淡出的效果。Vue在元素顯示與隱藏的過渡中,提供了 6 個 class 來切換:
v-enter
:定義進(jìn)入過渡的開始狀態(tài)。在元素被插入之前生效,在元素被插入之后的下一幀移除。
v-enter-active
:定義進(jìn)入過渡生效時的狀態(tài)。在整個進(jìn)入過渡的階段中應(yīng)用,在元素被插入之前生效,在過渡/動畫完成之后移除。這個類可以被用來定義進(jìn)入過渡的過程時間,延遲和曲線函數(shù)。
v-enter-to
: 2.1.8版及以上 定義進(jìn)入過渡的結(jié)束狀態(tài)。在元素被插入之后下一幀生效 (與此同時 v-enter
被移除),在過渡/動畫完成之后移除。
v-leave
: 定義離開過渡的開始狀態(tài)。在離開過渡被觸發(fā)時立刻生效,下一幀被移除。
v-leave-active
:定義離開過渡生效時的狀態(tài)。在整個離開過渡的階段中應(yīng)用,在離開過渡被觸發(fā)時立刻生效,在過渡/動畫完成之后移除。這個類可以被用來定義離開過渡的過程時間,延遲和曲線函數(shù)。
v-leave-to
: 2.1.8版及以上 定義離開過渡的結(jié)束狀態(tài)。在離開過渡被觸發(fā)之后下一幀生效 (與此同時 v-leave
被刪除),在過渡/動畫完成之后移除。
對于這些在過渡中切換的類名來說,如果你使用一個沒有名字的 <transition>
,則 v-
是這些類名的默認(rèn)前綴。如果你使用了 <transition name="my-transition">
,那么 v-enter
會替換為 my-transition-enter
。
v-enter-active
和 v-leave-active
可以控制進(jìn)入/離開過渡的不同的緩和曲線,在下面章節(jié)會有個示例說明。
通常我們都使用 CSS 過渡來實(shí)現(xiàn)效果。
如下實(shí)例:
CSS 動畫用法類似 CSS 過渡,但是在動畫中 v-enter 類名在節(jié)點(diǎn)插入 DOM 后不會立即刪除,而是在 animationend 事件觸發(fā)時刪除。
我們可以通過以下特性來自定義過渡類名:
enter-class
enter-active-class
enter-to-class
(2.1.8+)leave-class
leave-active-class
leave-to-class
(2.1.8+)自定義過渡的類名優(yōu)先級高于普通的類名,這樣就能很好的與第三方(如:animate.css)的動畫庫結(jié)合使用。
Vue 為了知道過渡的完成,必須設(shè)置相應(yīng)的事件監(jiān)聽器。它可以是 transitionend
或 animationend
,這取決于給元素應(yīng)用的 CSS 規(guī)則。如果你使用其中任何一種,Vue 能自動識別類型并設(shè)置監(jiān)聽。
但是,在一些場景中,你需要給同一個元素同時設(shè)置兩種過渡動效,比如 animation
很快的被觸發(fā)并完成了,而 transition
效果還沒結(jié)束。在這種情況中,你就需要使用 type
特性并設(shè)置 animation
或 transition
來明確聲明你需要 Vue 監(jiān)聽的類型。
在很多情況下,Vue 可以自動得出過渡效果的完成時機(jī)。默認(rèn)情況下,Vue 會等待其在過渡效果的根元素的第一個 transitionend
或 animationend
事件。然而也可以不這樣設(shè)定——比如,我們可以擁有一個精心編排的一系列過渡效果,其中一些嵌套的內(nèi)部元素相比于過渡效果的根元素有延遲的或更長的過渡效果。
在這種情況下你可以用 <transition>
組件上的 duration
屬性定制一個顯性的過渡持續(xù)時間 (以毫秒計(jì)):
<transition :duration="1000">...</transition>
你也可以定制進(jìn)入和移出的持續(xù)時間:
<transition :duration="{ enter: 500, leave: 800 }">...</transition>
可以在屬性中聲明 JavaScript 鉤子:
這些鉤子函數(shù)可以結(jié)合 CSS transitions/animations 使用,也可以單獨(dú)使用。
當(dāng)只用 JavaScript 過渡的時候,在 enter
和 leave
中必須使用 done
進(jìn)行回調(diào)。否則,它們將被同步調(diào)用,過渡會立即完成。
推薦對于僅使用 JavaScript 過渡的元素添加 v-bind:css="false"
,Vue 會跳過 CSS 的檢測。這也可以避免過渡過程中 CSS 的影響。
一個使用 Velocity.js 的簡單例子:
可以通過 appear
特性設(shè)置節(jié)點(diǎn)在初始渲染的過渡
<transition appear> <!-- ... --> </transition>
這里默認(rèn)和進(jìn)入/離開過渡一樣,同樣也可以自定義 CSS 類名。
<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>
自定義 JavaScript 鉤子:
<transition appear v-on:before-appear="customBeforeAppearHook" v-on:appear="customAppearHook" v-on:after-appear="customAfterAppearHook" v-on:appear-cancelled="customAppearCancelledHook" > <!-- ... --> </transition>
我們可以設(shè)置多個元素的過渡,一般列表與描述:
需要注意的是當(dāng)有相同標(biāo)簽名的元素切換時,需要通過 key
特性設(shè)置唯一的值來標(biāo)記以讓 Vue 區(qū)分它們,否則 Vue 為了效率只會替換相同標(biāo)簽內(nèi)部的內(nèi)容。
<transition> <table v-if="items.length > 0"> <!-- ... --> </table> <p v-else>抱歉,沒有找到您查找的內(nèi)容。</p> </transition>
如下實(shí)例:
<transition> <button v-if="isEditing" key="save"> Save </button> <button v-else key="edit"> Edit </button> </transition>
在一些場景中,也可以通過給同一個元素的 key
特性設(shè)置不同的狀態(tài)來代替 v-if
和 v-else
,上面的例子可以重寫為:
<transition> <button v-bind:key="isEditing"> {{ isEditing ? 'Save' : 'Edit' }} </button> </transition>
使用多個 v-if
的多個元素的過渡可以重寫為綁定了動態(tài)屬性的單個元素過渡。例如:
<transition> <button v-if="docState === 'saved'" key="saved"> Edit </button> <button v-if="docState === 'edited'" key="edited"> Save </button> <button v-if="docState === 'editing'" key="editing"> Cancel </button> </transition>
可以重寫為:
<transition> <button v-bind:key="docState"> {{ buttonMessage }} </button> </transition> // ... computed: { buttonMessage: function () { switch (this.docState) { case 'saved': return 'Edit' case 'edited': return 'Save' case 'editing': return 'Cancel' } } }