38-Vue脚手架-过渡与动画

发布时间 2023-11-09 09:43:42作者: 马铃薯1

Vue封装的过渡与动画

在插入、更新或移除 DOM 元素时,在合适的时候给元素添加样式类名

 

transition 讲解

transition 是 vue 内置的一个组件,我们可以直接使用。

<transition> 元素作为单个元素 / 组件的过渡效果。<transition>  只会把过渡效果应用到其包裹的内容上,而不会额外渲染 DOM 元素,也不会出现在可被检查的组件层级中


注意:<transition>  只能用来包裹单个元素,如果包裹了多个元素则用 <transition-group>
 
transition 组件上定义的属性:
1)name:string类型,用于自动生成 CSS 过渡类名。例如:name: 'hello' 将自动拓展为 .hello-enter.hello-enter-active 等。如果没有定义 name ,默认的类名前缀为 "v" ,例如 .v-enter
2)appear:boolean类型,表示是否在初始渲染时使用过渡。默认为 false。
3)type:string类型,指定过渡事件类型,侦听过渡何时结束。有效值为 "transition""animation"默认 Vue.js 将自动检测出持续时间长的为过渡事件类型。
4)mode:string类型,控制离开/进入过渡的时间序列。有效的模式有 "out-in""in-out"默认同时进行。
5)duration:number类型或者对象类型:{ enter: number, leave: number } ,用来指定过渡的持续时间。默认情况下,Vue 会等待过渡所在根元素的第一个 transitionend 或 animationend 事件。

实现过渡的原理,就是通过在某一时刻给 transition 包裹的的元素上动态添加和删除 class 类名的方式来实现(在合适的时候给元素添加样式类名)。
元素进入的样式(Enter):
  • v-enter进入的起点,在元素被插入之前生效,在元素被插入之后的下一帧移除。
  • v-enter-active进入的过程,在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡 / 动画完成之后移除。 这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
  • v-enter-to进入的终点,在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡 / 动画完成之后移除。

元素离开的样式(Leave):

  • v-leave离开的起点,在离开过渡被触发时立刻生效,下一帧被移除。
  • v-leave-active离开的过程,在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡 / 动画完成之后移除。 这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
  • v-leave-to离开的终点,在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡 / 动画完成之后移除。
 

1. 单元素 / 单组件的过渡

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

  • 条件渲染 (使用 v-if )
  • 条件展示 (使用 v-show )
  • 动态组件
  • 组件根节点

简单案例:

src/components/Test.vue

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <!--<Transition> 会在一个元素或组件进入和离开 DOM 时应用动画-->
    <transition>
      <h1 class="demo1" v-show="isShow">你好啊!我是Test</h1>
    </transition>

    <!--定义name为"hello",则后续格式应该用.hello-enter-active-->
    <!--:appear="true" 代表 appear属性 为true, 默认显示进入动画-->
    <transition name="hello" :appear="true">
      <h1 class="demo2" v-show="isShow">你好啊!我是Test</h1>
    </transition>
  </div>
</template>

<script>
  export default{
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Test",
    data(){
      return{
        isShow:true
      }
    }
  }
</script>

<style scoped>
  .demo1{
    background-color: orange;
  }
  .demo2{
    background-color: skyblue;
  }

  .v-enter-active{
    animation: malingshu 0.5s linear;
  }

  .v-leave-active{
    animation: malingshu 0.5s linear reverse;
  }

  .hello-enter-active{
    animation: malingshu 0.5s linear;
  }

  .hello-leave-active{
    animation: malingshu 0.5s linear reverse;
  }

  /* 动画 */
  @keyframes malingshu {
    from{
      transform: translateX(-100%);
    }
    to{
      transform: translateX(0px);
    }
  }

</style>

src/components/Test2.vue

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <!--<Transition> 会在一个元素或组件进入和离开 DOM 时应用动画-->
    <transition name="hello" :appear="true">
      <h1 class="demo2" v-show="isShow">你好啊!我是Test2</h1>
    </transition>
  </div>
</template>

<script>
  export default{
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Test2",
    data(){
      return{
        isShow:true
      }
    }
  }
</script>

<style scoped>
  .demo2{
    background-color: skyblue;
    //transition: 0.5s linear;
  }

  /* 进入的起点、离开的终点 */
  .hello-enter,.hello-leave-to{
    transform: translateX(-100%);
  }

  /* 进入的过程、离开的过程 */
  .hello-enter-active,.hello-leave-active{
    transition: 0.5s linear;
  }

  /* 进入的终点、离开的起点 */
  .hello-enter-to,.hello-leave,{
    transform: translateX(0);
  }

</style>

src/App.vue

<template>
  <div>
    <Test></Test>
    <hr/>
    <Test2></Test2>
  </div>
</template>

<script>
import Test from "@/components/Test.vue";
import Test2 from "@/components/Test2.vue";

export default {
  name: "App",
  components: {
    Test,
    Test2
  },
};
</script>

<style></style>

src/main.js

import Vue from "vue"
import App from "./App.vue"

// 阻止 vue 在启动时生成生产提示
Vue.config.productionTip = false

new Vue({
    el:"#app",
    render:h => h(App),
})

2. 多元素 / 多组件的过渡

在src/components/Test2.vue,使用<transition-group>标签,完成多个元素的过渡,且每个元素都要指定key值

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <!--多元素过渡,使用transition-group-->
    <transition-group name="hello" :appear="true">
      <!--里面的两个元素,互斥,一个显示则另一个不显示-->
      <h1 class="demo2" v-show="!isShow" key="1">你好啊!我是Test2</h1>
      <h1 class="demo2" v-show="isShow" key="2">你好啊!我是Test2</h1>
    </transition-group>
  </div>
</template>

<script>
  export default{
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Test2",
    data(){
      return{
        isShow:true
      }
    }
  }
</script>

<style scoped>
  .demo2{
    background-color: skyblue;
    //transition: 0.5s linear;
  }

  /* 进入的起点、离开的终点 */
  .hello-enter,.hello-leave-to{
    transform: translateX(-100%);
  }

  /* 进入的过程、离开的过程 */
  .hello-enter-active,.hello-leave-active{
    transition: 0.5s linear;
  }

  /* 进入的终点、离开的起点 */
  .hello-enter-to,.hello-leave,{
    transform: translateX(0);
  }


</style>

 

3. 第三方动画库 Animate.css

官方网址Animate.css | A cross-browser library of CSS animations.

安装 animate.css库

npm install animate.css --save

引入 animate.css库

import 'animate.css';

使用方法:

<transition :appear="true"
    name="animate__animated animate__bounce"
    enter-active-class="animate__swing"
    leave-active-class="animate__backOutDown"
>
    <h1 class="demo2"v-show="isShow"key="1">你好啊!我是Test3</h1>
</transition>

 在src/components/Test3.vue,完整代码:

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <!--多元素过渡,使用transition-group-->
    <transition
        :appear="true"
        name="animate__animated animate__bounce"
        enter-active-class="animate__swing"
        leave-active-class="animate__backOutDown"
    >
      <h1 class="demo2" v-show="isShow" key="1">你好啊!我是Test3</h1>
    </transition>
  </div>
</template>

<script>
  import "animate.css"

  export default{
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Test3",
    data(){
      return{
        isShow:true
      }
    }
  }
</script>

<style scoped>
  .demo2{
    background-color: skyblue;
    //transition: 0.5s linear;
  }
</style>