Vue动画原理

119 阅读2分钟

cn.vuejs.org/v2/guide/tr…

概述

Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。包括以下工具:

  • 在 CSS 过渡和动画中自动应用 class

  • 可以配合使用第三方 CSS 动画库,如 Animate.css

  • 在过渡钩子函数中使用 JavaScript 直接操作 DOM

  • 可以配合使用第三方 JavaScript 动画库,如 Velocity.js

transition过渡

Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡

  • 条件渲染 (使用 v-if)

  • 条件展示 (使用 v-show)

  • 动态组件

  • 组件根节点

<div id="demo"> 
  <button v-on:click="show = !show"> 
    Toggle
  </button> 
  <transition name="fade"> 
    <p v-if="show">hello</p>
  </transition>
</div>
new Vue({ 
  el: '#demo', 
  data: { 
    show: true 
  } 
})
.fade-enter-active, .fade-leave-active { 
  transition: opacity .5s; 
} 
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { 
  opacity: 0; 
}

过度的类名

image.png

image.png

CSS 过渡

image.png

image.png

animationend

<div id="example-2"> 
  <button @click="show = !show">Toggle show</button> 
  <transition name="bounce"> 
    <p v-if="show">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris facilisis enim libero, at lacinia diam fermentum id. Pellentesque habitant morbi tristique senectus et netus.</p> 
  </transition> 
</div>
new Vue({ 
  el: '#example-2', 
  data: { 
    show: true 
  } 
})
.bounce-enter-active { 
  animation: bounce-in .5s; 
} 
.bounce-leave-active { 
  animation: bounce-in .5s reverse; 
} 
@keyframes bounce-in { 
  0% { 
    transform: scale(0); 
  } 
  50% { 
    transform: scale(1.5); 
  } 
  100% { 
    transform: scale(1); 
  } 
}

自定义过渡类名

image.png

同时使用过渡和动画

image.png

image.png

JavaScript钩子

<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>
// ... 
methods: { 
  // -------- 
  // 进入中 
  // -------- 
  beforeEnter: function (el) { 
  // ... 
  }, 
  // 当与 CSS 结合使用时 
  // 回调函数 done 是可选的 
  enter: function (el, done) { 
  // ... 
    done() 
  }, 
  afterEnter: function (el) { 
    // ... 
  }, 
  enterCancelled: function (el) { 
    // ... 
  }, 
    // -------- 
    // 离开时 
    // -------- 
  beforeLeave: function (el) { 
    // ... 
  }, 
    // 当与 CSS 结合使用时 
    // 回调函数 done 是可选的 
  leave: function (el, done) { 
    // ... done() 
  }, 
  afterLeave: function (el) { 
    // ... 
  }, 
    // leaveCancelled 只用于 v-show 中 
  leaveCancelled: function (el) { 
    // ... 
  } 
}

image.png

image.png

image.png

多元素动画

image.png

  • 注意: 一定要加key,如果不加,vue会认为这是同一个button,就是把on变成了off,不知道他们的区别。

同时生效的进入和离开的过渡不能满足所有要求,所以 Vue 提供了过渡模式

  • in-out:新元素先进行过渡,完成之后当前元素过渡离开。

  • out-in:当前元素先进行过渡,完成之后新元素过渡进入。

<transition name="fade" mode="out-in"> 
  <!-- ... the buttons ... --> 
</transition>

image.png

image.png

列表过渡

image.png

<div id="list-demo" class="demo"> 
  <button v-on:click="add">Add</button> 
  <button v-on:click="remove">Remove</button> 
  <transition-group name="list" tag="p"> 
    <span v-for="item in items" v-bind:key="item" class="list-item"> 
      {{ item }} 
    </span>
  </transition-group> 
</div>
new Vue({ 
  el: '#list-demo', 
  data: { 
    items: [1,2,3,4,5,6,7,8,9], 
    nextNum: 10 
  }, 
  methods: { 
    randomIndex: function () { 
      return Math.floor(Math.random() * this.items.length) 
    }, 
    add: function () { 
      this.items.splice(this.randomIndex(), 0, this.nextNum++) 
    }, 
    remove: function () { 
      this.items.splice(this.randomIndex(), 1) 
    },
  } 
})
.list-item { 
  display: inline-block; 
  margin-right: 10px; 
} 
.list-enter-active, .list-leave-active { 
  transition: all 1s; 
} 
.list-enter, .list-leave-to 
 /* .list-leave-active for below version 2.1.8 */ { 
  opacity: 0; 
  transform: translateY(30px); 
}