Vue.js笔记8—过渡与动画

93 阅读3分钟

过渡和动画

过渡的类名

  1. [name]-enter:进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。

  2. [name]-enter-active:进入过渡生效时的状态。在元素被插入之前生效,在过渡/动画完成之后移除。用来定义进入过渡的过程时间,延迟和曲线函数。

  3. [name]-enter-to:进入过渡的结束状态。在元素被插入之后下一帧生效 ,在过渡/动画完成之后移除。

  4. [name]-leave:离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。

  5. [name]-leave-active:离开过渡生效时的状态在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。

  6. [name]-leave-to:定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 ,在过渡/动画完成之后移除。

    image.png

单元素/组件的过渡

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

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

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

  • 动态组件

  • 组件根节点

1. css过渡例子

  1. transition包裹元素,并命名

    <button @click="show = !show">切换</button>
    <transition name="fade">
        <p v-if="show">hello</p>
    </transition>
    
  2. 定义类

    //进入过渡
    .fade-enter-active {
      transition: all .3s ease;
    }
    //离开过渡
    .fade-leave-active {
      transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
    }
    //开始和结束的状态
    .fade-enter, .fade-leave-to {
      transform: translateX(10px);
      opacity: 0;
    }
    

2. css动画例子

  1. transition包裹元素,并命名

    <button @click="show = !show">切换</button>
    <transition name="bounce">
        <p v-if="show">hello</p>
    </transition>
    
  2. 定义类

    //进入动画
    .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);
      }
    }
    

多个元素/组件过渡

1. 多个元素

<transition>
  <table v-if="items.length > 0"></table>
  <p v-else>Sorry, no items found.</p>
</transition>

当有相同标签名的元素切换时,需要通过 key 设置唯一的值来标记以让 Vue 区分它们

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

2. 多个组件

不需要使用 key 。相反,需要使用动态组件

<input type="radio" value="com1" id="1"  v-model="view">com1
<input type="radio" value="com2" id="2"  v-model="view">com2
<transition name="fade" mode="out-in">
  <component v-bind:is="view"></component>
</transition>
new Vue({
  el: '#app',
  data: {
    view: 'com1'
  },
  components: {
    'com1': {template: '<div>Component A</div>'},
    'com2': {template: '<div>Component B</div>'}
  }
})
.fade-enter-active, .fade-leave-active {
  transition: opacity .3s ease;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}

3. 过渡模式

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

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

    <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
    <div id="app">
      <button @click="show = !show">
        Toggle
      </button>
      <transition
        v-on:before-enter="beforeEnter"
        v-on:enter="enter"
        v-on:leave="leave"
        v-bind:css="false"
      >
        <p v-if="show">
          Demo
        </p>
      </transition>
    </div>
    
    new Vue({
      el: '#pp
      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 })
        }
      }
    })
    

初始渲染的过渡

可以通过 appear 设置节点在初始渲染的过渡,只渲染一次

<transition
  appear
  appear-class="enter-class"
  appear-active-class="enter-active-class"
  appear-to-class="enter-to-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>

列表过渡

同v-for渲染列表时,使用<transition-group>组件。需要提供key,此时过渡模式不可用。

不同于 transition,它会以一个真实元素呈现:默认为一个 span。你也可以通过 tag attribute 更换为其他元素。

<div id="app">
  <!--... -->
  <transition-group name="list" tag="p">
    <span v-for="item in items" :key="item">
      {{ item }}
    </span>
  </transition-group>
</div>