Vue动画

85 阅读2分钟

CSS 过渡和动画

transition

常用的过渡是 CSS 过渡,使用 fade

<template>
  <div id="app">
    <button @click="Toggle">Toggle</button>
    <transition name="fade">
      <p v-if="visible">test</p>
    </transition>
  </div>
</template>

<script>
export default {
  data(){
    return{
      visible:false
    }
  },
  methods:{
    Toggle(){
      this.visible=!this.visible
    }
  }
};
</script>

<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity .25s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}
</style>

效果

从上面例子中可以看出来,当用户点击按钮时,Vue 会给目标元素插入一个CSS类名,当动画完成时,会删除这个类名,

过渡类名

  • v-enter:进入过渡
  • v-enter-active:过渡生效时,这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数
  • v-enter-to:过渡的结束状态
  • v-leave:离开过渡开始时
  • v-leave-active:离开过渡生效时,这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数
  • v-leave-to:离开过渡结束时

animation

<template>
  <div id="app">
    <button @click="Toggle">Toggle</button>
    <transition name="fade">
      <p v-if="visible">test</p>
    </transition>
  </div>
</template>

<script>
export default {
  data(){
    return{
      visible:false
    }
  },
  methods:{
    Toggle(){
      this.visible=!this.visible
    }
  }
};
<style>
@keyframes bounce-in{
  0%{
    transform: scale(0)
  }
  50%{
    transform: scale(1.2)
  }
  100%{
    transform: scale(1)
  }
}
.bounce-enter-active{
  animation: bounce-in .25s
}
 .bounce-leave-active {
  animation: bounce-in .25s reverse
}
</style>

效果

transition 不同的是animationv-enter类名在节点插入DOM后不会立即删除,而是在 animationend事件触发时删除。

自定义过渡的类名

我们可以通过以下 attribute 来自定义过渡类名:

  • enter-class
  • enter-active-class
  • enter-to-class
  • leave-class
  • leave-active-class
  • leave-to-class

优先级高于普通类名,Vue 的过渡系统可以和 Animate.css等CSS 动画库结合使用

HTML

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
  	<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
	<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="app">
    <button @click="visible=!visible">Toggle</button>
     <transition enter-active-class="animated fadeInDownBig" leave-active-class="animated fadeOutDownBig">
      <p v-if="visible">test</p>
    </transition>
  </div>
</body>
</html>

JS

new Vue({
 el: '#app',
 data:{
   visible:false
}
});

效果

JS 操作动画

可以在 attribute 中声明 JavaScript 钩子

  • 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"

HTML

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
  	<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
	<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
  <script src="https://cdn.bootcdn.net/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
</head>
<body>
<div id="app">
    <button @click="visible=!visible">Toggle</button>
     <transition 
                 v-on:before-enter="beforeEnter"
                 v-on:enter="enter"
                 v-on:leave="leaveEnter"
                 v-bind:css="false"
                 >
      <p v-if="visible">test</p>
    </transition>
  </div>
</body>
</html>

JS

new Vue({
  el: '#app',
  data:{
	visible:false
},
  methods:{
    beforeEnter:function(el){
      el.style.opacity=0;
    },
    enter:function(el){
      Velocity(el,{opacity:1},{duration:1000});
    },
    leaveEnter:function(el,done){
      Velocity(el,{opacity:0},{complete:done});
    }
  }
});

效果

这些钩子函数可以结合 CSS transitions/animations 使用,也可以单独使用。

多元素过渡

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

  • in-out:新元素先进行过渡,完成之后当前元素过渡离开。
  • out-in:当前元素先进行过渡,完成之后新元素过渡进入。
<transition name="fade" mode="out-in">...</transition>

多组件过渡

多个组件的过渡只需要使用动态组件

HTML

<transition name="component-fade" mode="out-in">
  <component v-bind:is="view"></component>
</transition>

JS

new Vue({
  el: '#transition-components-demo',
  data: {
    view: 'v-a'
  },
  components: {
    'v-a': {
      template: '<div>Component A</div>'
    },
    'v-b': {
      template: '<div>Component B</div>'
    }
  }
})

列表过渡

 <transition-group name="flip-list" tag="ul">
    <li v-for="item in items" v-bind:key="item">
      {{ item }}
    </li>
  </transition-group>

在渲染时,<transition-group> 默认时一个<span>,在上面的例子中 tag 的值 ul 会作为标签替换 <transition-group> 标签

其他

  • 可复用过渡:将 <transition> 或者 <transition-group> 作为根组件,然后将任何子组件放置在其中就可复用

  • 动态过渡

    在 Vue 中即使是过渡也是数据驱动的!动态过渡最基本的例子是通过 name attribute 来绑定动态值。

    <transition v-bind:name="transitionName">
        <!-- ... -->
    </transition>