vue 巧用過渡效果

vue提供的了transition組件來實現組件的過渡和路由的過渡,合理使用這個組建可讓咱們的頁面更加的靈活,提升用戶體驗。css

概念

在進入/離開的過渡中, 會有6個class的切換, 抄一張官方的圖 html

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

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

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

v-leave: 定義離開過渡的開始狀態。在離開過渡被觸發時馬上生效,下一幀被移除。dom

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

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

看起來仍是有有點亂,先來捋一下。動畫

enter 定義開始的狀態, active定義過程, enter定義結束, 可是在實際進行的時候是有交叉的。 經過斷點能夠發現,ui

  • 添加v-enter
  • 添加v-enter-active,
  • 卸載v-enter
  • 添加v-ernter-to
  • 卸載v-enter-to和v-enter-active
// transition: all 2s; 
    .move-enter {
      margin-left: 0;
    }
    .move-enter-active {
       margin-left: 100px;
    }
    .move-enter-to {
      margin-left: 200px;
    }
複製代碼

例如在上面這種狀況下, 過渡動畫會怎麼進行呢?

這裏要注意兩點。

  • enter-active覆蓋掉了enter的起點位置
  • 一共通過了兩次過渡, enter-to是在active結束以後開始的, 因此第四秒, 纔回到dom元素自己的位置。

因此官方文檔之, 也是使用v-enter定義起點位置, 在enter-active中控制效果。

利用class實現過渡效果

在這6個class之上, 利用transition或者動畫, 均可以實現咱們須要的效果。 舉個栗子, 這裏咱們直接將全部的路由改變都定義一個過渡效果,

appear屬性表示頁面初次加載的時候也適用於動畫

<transition appear name="move">
        <router-view></router-view>
    </transition>
複製代碼
@keyframes animationIn {
  0% {
    transform: translate(-100%, 0);
  }
  100% {
    transform: translate(0, 0);
  }
}
@keyframes animationOut {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(100%, 0);
  }
}

.move-enter {
  transform: translate(-100%, 0);
  position: absolute!important;
  z-index: 999;
  top: 0;
  left: 0;
  width: 100%;
}
.move-enter-active {
  animation: animationIn 0.2s;
  position: absolute!important; // 進入的組件要覆蓋掉移除的組件,參考 //https://cn.vuejs.org/v2/guide/transitions.html#%E8%BF%87%E6%B8%A1%E6%A8%A1%E5%BC%8F
  z-index: 999;
  top: 0;
  left: 0;
  width: 100%;
}
.move-leave {
  transform: translate(0, 0);
}
.move-leave-active {
  animation: animationOut 0.2s;
}

複製代碼

效果

JavaScript 鉤子

這些鉤子函數能夠結合 CSS transitions/animations 使用

<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>
複製代碼

在這些鉤子中, 可使用其餘第三方庫,回調中的el將是真實的dom元素 舉個栗子, 這裏使用了官方推薦的Velocity.js做爲動畫庫

<div class="main">
      <transition name="showRect" appear
                  @before-enter="handleBeforeEnter"
                  @enter="handleEnter"
                  @after-enter="handleAfterEnter"
                  @before-leave="handleBeforeLeave"
                  @leave="handleLeave"
                  @after-leave="handleAfterLeave"
                  :css="false">
        <div class="box" v-if="show"></div>
      </transition>
    </div>
    <button @click="start">切換</button>
複製代碼
methods: {
      start() {
        this.show = !this.show
      },
      handleBeforeEnter: function (el) {
        el.style.opacity = 0;
        console.log('方塊顯示動畫即將執行');
      },
      handleEnter: function (el, done) {
        Velocity(el, 'stop');
        Velocity(el, {
          backgroundColor: '#0085eb',
          opacity: 1,
          translateX: 260,
          rotateZ: ['360deg', 0]
        }, {
          duration: 1000,
          easing: [ 0.4, 0.01, 0.165, 0.99 ],
          complete: done
        });
        console.log('方塊顯示動畫執行中...');
      },
      handleAfterEnter: function (el) {
        console.log('方塊顯示動畫結束');
      },
      handleBeforeLeave: function (el) {
        console.log('方塊隱藏動畫即將執行');
      },
      handleLeave: function (el, done) {
        Velocity(el, 'stop');
        Velocity(el, {
          backgroundColor: '#4dd0e1',
          opacity: 0,
          translateX: 0,
          rotateZ: [0, '360deg']
        }, {
          duration: 1000,
          easing: [ 0.4, 0.01, 0.165, 0.99 ],
          complete: done
        });
        console.log('方塊隱藏動畫執行中...');
      },
      handleAfterLeave: function (el) {
        console.log('方塊隱藏動畫結束');
      }
    }
複製代碼

列表過渡

vue還提供了transition-group組件, 做爲列表過渡的容器

不一樣於 ,它會以一個真實元素呈現:默認爲一個 。你也能夠經過 tag 特性更換爲其餘元素

transition-group 擁特別的v-move屬性,它會在元素的改變定位的過程當中應用, 效果可參見官網。

其餘的就不抄官網了

列表過渡中, 能夠結合js鉤子, 實現一些特殊的效果

舉個栗子

<template>
  <div>
    <div class="btn" @click="addItem">添加</div>
    <div class="btn" @click="sort">排序</div>
    <div class="box">
      <div class="item-bar">
        <transition-group name="fade" tag="p" appear
        v-on:before-enter="beforeEnter"
        v-on:after-enter="afterEnter">
        // 這裏的data-index 是一個識別標識, 便於在js鉤子中得到當前元素的序號
          <div class="item" v-for="(i, index) in list" :key="i" :data-index="index">{{i}}</div>
        </transition-group>
      </div>
    </div>
  </div>
</template>
複製代碼
<script lang="ts">
  import Vue from "vue";
  export default Vue.extend({
    name: "home",
    data() {
      return {
        show: true,
        list: [5,4,3,2,1],
        nextNum: 6
      };
    },
    methods: {
      showDom() {
        this.show = !this.show
      },
      beforeEnter: function (el: any) {
        el.style.opacity = 0 // 每一個元素插入以前, 透明度爲0
        let index = el.dataset.index  每次可能插入多個元素,
        // 頁面加載時先展現5個
        if (index < 5) {
            //設置動畫延遲, 實現按續插入的效果
          el.style.animationDelay = el.dataset.index * 0.3 + 's'
        }
      },
      afterEnter: function (el) {
        el.style.opacity = 1
        console.log('afterEnter')
      },
      addItem() {
        this.list.push(this.nextNum++)
      },
      sort() {
        this.list = this.list.sort((a, b) => a -b)
      }
    }
  });
</script>
複製代碼
@keyframes animat {
    0% {
      margin-left: 300px;
      opacity: 0;
    }
    100% {
      margin-left: 0;
      opacity: 1;
    }
  }
  .fade-enter {
    opacity: 0;
    margin-left: 300px;
  }
  .fade-enter-active {
    opacity: 0;
    animation: animat 1s;
  }
  .fade-enter-to {
    opacity: 1;
    margin-left: 0;
  }

  .fade-move {
    transition: all 0.3s;
  }
  .fade-leave {
    left: 10px;
  }
  .fade-leave-active {
    transition: all 2s ease-out;
  }
  .fade-leave-to {
    left: -100%;
  }
複製代碼

效果

以上~

相關文章
相關標籤/搜索