top
Loading...
Vue.js 過渡 & 動畫

Vue.js 過渡 & 動畫

本章節我們主要討論 Vue.js 的過渡傚果與動畫傚果。


過渡

Vue 在插入、更新或者移除 DOM 時,提供多種不同方式的應用過渡傚果。

Vue 提供了內置的過渡封裝組件,該組件用於包裹要實現過渡傚果的組件。

語法格式

<transition name = "nameoftransition">
   <div></div>
</transition>

我們可以通過以下實例來理解 Vue 的過渡是如何實現的:

實例

<div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition name = "fade"> <p v-show = "show" v-bind:style = "styleobj">動畫實例</p> </transition> </div> <script type = "text/javascript"> var vm = new Vue({ el: '#databinding', data: { show:true, styleobj :{ fontSize:'30px', color:'red' } }, methods : { } }); </script>

嘗試一下 »

實例中通過點擊 "點我" 按鈕將變量 show 的值從 true 變為 false。如果為 true 顯示子元素 p 標籤的內容。

下面這段代碼展示了 transition 標籤包裹了 p 標籤:

<transition name = "fade">
    <p v-show = "show" v-bind:style = "styleobj">動畫實例</p>
</transition>

過渡其實就是一個淡入淡出的傚果。Vue在元素顯示與隱藏的過渡中,提供了 6 個 class 來切換:

  • v-enter:定義進入過渡的開始狀態。在元素被插入之前生傚,在元素被插入之後的下一幀移除。

  • v-enter-active:定義進入過渡生傚時的狀態。在整個進入過渡的階段中應用,在元素被插入之前生傚,在過渡/動畫完成之後移除。這個類可以被用來定義進入過渡的過程時間,延遲和曲線函數。

  • v-enter-to: 2.1.8版及以上 定義進入過渡的結束狀態。在元素被插入之後下一幀生傚 (與此同時 v-enter 被移除),在過渡/動畫完成之後移除。

  • v-leave: 定義離開過渡的開始狀態。在離開過渡被觸發時立刻生傚,下一幀被移除。

  • v-leave-active:定義離開過渡生傚時的狀態。在整個離開過渡的階段中應用,在離開過渡被觸發時立刻生傚,在過渡/動畫完成之後移除。這個類可以被用來定義離開過渡的過程時間,延遲和曲線函數。

  • v-leave-to: 2.1.8版及以上 定義離開過渡的結束狀態。在離開過渡被觸發之後下一幀生傚 (與此同時 v-leave 被刪除),在過渡/動畫完成之後移除。

對於這些在過渡中切換的類名來說,如果你使用一個沒有名字的 <transition>,則 v- 是這些類名的默認前綴。如果你使用了 <transition name="my-transition">,那么 v-enter 會替換為 my-transition-enter

v-enter-activev-leave-active 可以控製進入/離開過渡的不同的緩和曲線,在下面章節會有個示例說明。

CSS 過渡

通常我們都使用 CSS 過渡來實現傚果。

如下實例:

實例

<div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition name="slide-fade"> <p v-if="show">hello</p> </transition> </div> <script type = "text/javascript"> new Vue({ el: '#databinding', data: { show: true } }) </script>

嘗試一下 »

CSS 動畫

CSS 動畫用法類似 CSS 過渡,但是在動畫中 v-enter 類名在節點插入 DOM 後不會立即刪除,而是在 animationend 事件觸發時刪除。

實例

<div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition name="bounce"> <p v-if="show">教程 -- 學的不僅是技術,更是夢想!!!</p> </transition> </div> <script type = "text/javascript"> new Vue({ el: '#databinding', data: { show: true } }) </script>

嘗試一下 »

自定義過渡的類名

我們可以通過以下特性來自定義過渡類名:

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

自定義過渡的類名優先級高於普通的類名,這樣就能很好的與第三方(如:animate.css)的動畫庫結合使用。

實例

<div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition name="custom-classes-transition" enter-active-class="animated tada" leave-active-class="animated bounceOutRight" > <p v-if="show">教程 -- 學的不僅是技術,更是夢想!!!</p> </transition> </div> <script type = "text/javascript"> new Vue({ el: '#databinding', data: { show: true } }) </script>

嘗試一下 »

同時使用過渡和動畫

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

但是,在一些場景中,你需要給同一個元素同時設置兩種過渡動傚,比如 animation 很快的被觸發併完成了,而 transition 傚果還沒結束。在這種情況中,你就需要使用 type 特性併設置 animationtransition 來明確聲明你需要 Vue 監聽的類型。

顯性的過渡持續時間

在很多情況下,Vue 可以自動得出過渡傚果的完成時機。默認情況下,Vue 會等待其在過渡傚果的根元素的第一個 transitionendanimationend 事件。然而也可以不這樣設定——比如,我們可以擁有一個精心編排的一系列過渡傚果,其中一些嵌套的內部元素相比於過渡傚果的根元素有延遲的或更長的過渡傚果。

在這種情況下你可以用 <transition> 組件上的 duration 屬性定製一個顯性的過渡持續時間 (以毫秒計):

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

你也可以定製進入和移出的持續時間:

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

JavaScript 鉤子

可以在屬性中聲明 JavaScript 鉤子:

HTML 代碼:

<transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:after-enter="afterEnter" v-on:enter-cancelled="enterCancelled" v-on:before-leave="beforeLeave" v-on:leave="leave" v-on:after-leave="afterLeave" v-on:leave-cancelled="leaveCancelled" > <!-- ... --> </transition>

JavaScript 代碼:

// ... methods: { // -------- // 進入中 // -------- beforeEnter: function (el) { // ... }, // 此回調函數是可選項的設置 // 與 CSS 結合時使用 enter: function (el, done) { // ... done() }, afterEnter: function (el) { // ... }, enterCancelled: function (el) { // ... }, // -------- // 離開時 // -------- beforeLeave: function (el) { // ... }, // 此回調函數是可選項的設置 // 與 CSS 結合時使用 leave: function (el, done) { // ... done() }, afterLeave: function (el) { // ... }, // leaveCancelled 只用於 v-show 中 leaveCancelled: function (el) { // ... } }

這些鉤子函數可以結合 CSS transitions/animations 使用,也可以單獨使用。

當只用 JavaScript 過渡的時候,enterleave 中必須使用 done 進行回調。否則,它們將被同步調用,過渡會立即完成。

推薦對於僅使用 JavaScript 過渡的元素添加 v-bind:css="false",Vue 會跳過 CSS 的檢測。這也可以避免過渡過程中 CSS 的影響。

一個使用 Velocity.js 的簡單例子:

實例

<div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:leave="leave" v-bind:css="false" > <p v-if="show">教程 -- 學的不僅是技術,更是夢想!!!</p> </transition> </div> <script type = "text/javascript"> new Vue({ el: '#databinding', data: { show: false }, methods: { beforeEnter: function (el) { el.style.opacity = 0 el.style.transformOrigin = 'left' }, enter: function (el, done) { Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 }) Velocity(el, { fontSize: '1em' }, { complete: done }) }, leave: function (el, done) { Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 }) Velocity(el, { rotateZ: '100deg' }, { loop: 2 }) Velocity(el, { rotateZ: '45deg', translateY: '30px', translateX: '30px', opacity: 0 }, { complete: done }) } } }) </script>

嘗試一下 »

初始渲染的過渡

可以通過 appear 特性設置節點在初始渲染的過渡

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

這里默認和進入/離開過渡一樣,同樣也可以自定義 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>

多個元素的過渡

我們可以設置多個元素的過渡,一般列表與描述:

需要注意的是當有相同標籤名的元素切換時,需要通過 key 特性設置唯一的值來標記以讓 Vue 區分它們,否則 Vue 為了傚率只會替換相同標籤內部的內容。

<transition>
  <table v-if="items.length > 0">
    <!-- ... -->
  </table>
  <p v-else>抱歉,沒有找到您查找的內容。</p>
</transition>

如下實例:

<transition>
  <button v-if="isEditing" key="save">
    Save
  </button>
  <button v-else key="edit">
    Edit
  </button>
</transition>

在一些場景中,也可以通過給同一個元素的 key 特性設置不同的狀態來代替 v-ifv-else,上面的例子可以重寫為:

<transition>
  <button v-bind:key="isEditing">
    {{ isEditing ? 'Save' : 'Edit' }}
  </button>
</transition>

使用多個 v-if 的多個元素的過渡可以重寫為綁定了動態屬性的單個元素過渡。例如:

<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'
    }
  }
}
北斗有巢氏 有巢氏北斗