Vue学习之旅Part7:三种Vue的动画实现方式及列表的动画效果

一、动画实现方式

在Vue中 有三种动画的实现方式 分别是:

  • 使用过渡类名实现
  • 使用第三方animate.css实现
  • 使用钩子函数实现

下面将一一介绍:

1、使用过渡类名实现

首先 来了解一下动画的过渡类名:
Vue学习之旅Part7:三种Vue的动画实现方式及列表的动画效果
( 这是我在Vue官网找到的一个示意图 )

动画 实际上是分成了[ 进入 ]和[ 离开 ]这两部分

每个动画有两个时间点一个时间段

例如 对于进入(Enter)动画:
两个时间点是v-enter和v-enter-to
一个时间段是v-enter-active

进入 是一个半场动画
退出 也是一个半场动画
两个半场动画组成了一个完整的动画

v-enterv-leave-to样式是未激活样式 可视为一组
v-enter-tov-leave样式是激活样式 同样可视为一组

实现步骤

①、首先 使用<transition>标签将需要被动画控制的元素包裹起来

<transition>是Vue提供的一个组件 可以给元素和组件添加进入/离开过渡

<div id="app">
	<input type="button" value="toggle" @click="flag=!flag">
	<transition>
		<h3 v-if="flag">H3</h3>
	</transition>
</div>
②、然后 添加自定义样式来控制<transition>内部的元素 实现动画

为过渡类名设置样式:

  • v-enter 动画进入前
  • v-enter-to 动画进入后
  • v-leave 动画离开前
  • v-leave-to 动画离开后
  • ========================
  • v-enter-active 动画进入的整个过程
  • v-leave-active 动画离开的整个过程
<style>
	.v-enter, /* 进入之前元素的起始状态 此时还未开始进入 */
	.v-leave-to /* 动画离开之后的终止状态 此时动画结束 */
	{
		opacity: 0;
		transform: translateX(100px);
	}
	
	.v-enter-active, /* 入场动画的时间段 */
	.v-leave-active /* 离场动画的时间段 */
	{
		transition: all 0.4s ease;
	}
</style>

简单两步 即可使用过渡类名实现动画的效果

自定义前缀

默认的过渡类名带有以v-开头的前缀
可以给<transition>指定一个自定义的name值 作为自定义的前缀

其实 自定义前缀的目的并不是为了个性 也不是为了好看 而是为了区别不同组的动画
因为 在一个页面中可能有不止一个动画 默认的v-过渡类名只能控制一个动画

<!-- 为transition指定name 之后 调用该动画就用该指定的前缀 而不是默认的v-了 -->
<transition name="my">
	<h6 v-if="flag">H3</h6>
</transition>

在设置样式的时候 就可以用自定义的name作为前缀来设置样式了:
比如 我设置的是my 那么就以my作为前缀来设置动画的样式

<style>
	.my-enter, /* 进入之前元素的起始状态 此时还未开始进入 */
	.my-leave-to /* 动画离开之后的终止状态 此时动画结束 */
	{
		opacity: 0;
		transform: translateY(100px);
	}
	
	.my-enter-active, /* 入场动画的时间段 */
	.my-leave-active /* 离场动画的时间段 */
	{
		transition: all 0.4s ease;
	}
</style>

2、使用animate.css实现

animate.css是个著名的第三方的动画样式包
因此 使用前需导入css文件
Github地址
官网:Animate.css

cdn:

<link rel="stylesheet" href="https://unpkg.com/animate.css@3.5.2/animate.min.css">

既然使用第三方样式 就无须自己再去<style>里设置样式了 直接用现成的
animate.css提供了很多样式 可去官网查询 官网首页自带演示

虽然不用自己写样式 但还是要用<transition>进行包裹
enter-active-class属性指定入场时的样式类 用leave-active-class属性指定出场时的样式类
另 样式不能直接使用 须在前面加上animated 代表该类是个基本动画类

举个栗子:
入场动画使用bounceIn 离场动画使用bounceOut (这些动画都是自带的)

<div id="app">
	<!-- 样式不能直接使用 须在前面加上animated 代表该类是基本动画类 -->
	<transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut">
		<h3 v-if="flag">H3</h3>
	</transition>
</div>
<transition enter-active-class="bounceIn" leave-active-class="bounceOut">
	<!-- animated类也可以加在元素上面 这样 animated只需写一次了 -->
	<h3 v-if="flag" class="animated">H3</h3>
</transition>
<!-- 使用属性绑定duration 统一设置动画时长(单位:毫秒) -->
<transition enter-active-class="bounceIn" leave-active-class="bounceOut" v-bind:duration="600">
	<h3 v-if="flag" class="animated">H3</h3>
</transition>
<!-- 分别指定入场和离场时间 给duration传递一个对象 -->
<transition enter-active-class="bounceIn" leave-active-class="bounceOut" v-bind:duration="{enter:800,leave:200}">
	<h3 v-if="flag" class="animated">H3</h3>
</transition>

3、使用钩子函数实现

此处仅演示半场动画 整个完整的动画就是由两个半场动画组合而成的

半场动画 即意为只有一半的动画
比如 只有进入动画 没有退出动画
或 只有退出动画 没有进入动画

应用场景:动画只需要单程执行的
比如 在购物的时候 点击添加到购物车 然后会有一个红色小球跳到下方的购物车图标中

使用前 需先在属性中声明钩子函数:

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

然后 就是在Vue实例中写样式方法了

动画钩子函数 也可称作是 动画的生命周期函数

例:
(还是要使用<transition>标签包裹)

<div id="app">
	<!-- @before-enter 进入前 -->
	<!-- @enter 进入时 -->
	<!-- @after-enter 进入后 -->
	<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
		<div class="ball" v-show="flag"></div>
	</transition>
</div>

有两个需要注意的地方:

  • 1、需要使用el.offsetWidth强制动画刷新 若不写 则无法显示动画效果
    当然 offsetHeight offsetTop offsetLeft也行 只要跟offset有关的都可以
  • 2、要在enter方法中调用done() 代表动画的结束
    这个done其实就是afterEnter对函数的引用
    当只用JavaScript过渡的时候 在enter和leave中必须使用done进行回调 否则它们将被同步调用 过渡会立即完成
<script>
  var vm=new Vue({
     el:'#app',
     data:{
         flag:false
     },
     methods:{
         // 参数的el表示指定动画的DOM元素 是个原生的JS DOM对象
         beforeEnter(el)
         {
             // 动画入场前 此时 动画尚未开始 可设置元素的起始样式
             el.style.transform="translate(0,0)";
         },
         enter(el,done)
         {
             // 强制动画刷新 不写无法显示动画效果 offsetHeight offsetTop offsetLeft也行
             el.offsetWidth
             // 动画开始之后的样式 可设置动画完成动画之后的结束状态
             el.style.transform="translate(150px,450px)";
             el.style.transition="all 1s ease";

             // 调用done() 代表动画结束
             done();
         },
         afterEnter(el)
         {
             // 动画完成后
             this.flag=!this.flag;
         }
     }
  });
</script>

二、列表动画

列表动画 顾名思义 就是对列表设置的动画

1、在添加列表时设置动画

在实现列表过渡的时候 若需要过渡的元素是通过v-for渲染出来的
则不能使用transition包裹 需使用<transition-group>

<ul>
	<!-- 若要为v-for循环创建的元素设置动画 则必须为每一个元素设置:key属性 -->
	<transition-group>
		<li v-for="item in list" v-bind:key="item.id">
			编号:{{item.id}} === 姓名:{{item.name}}
		</li>
	</transition-group>
</ul>

然后 用过渡类名设置动画的样式即可:

<style>
	.v-enter, /* 进入之前元素的起始状态 此时还未开始进入 */
	.v-leave-to /* 动画离开之后的终止状态 此时动画结束 */
	{
	    opacity: 0;
	    transform: translateY(100px);
	}
	
	.v-enter-active, /* 入场动画的时间段 */
	.v-leave-active /* 离场动画的时间段 */
	{
	    transition: all 0.4s ease;
	}
</style>

2、在删除列表时设置动画

<transition-group>
	<li v-for="(item,i) in list" v-bind:key="item.id" @click="del(i)">
		编号:{{item.id}} === 姓名:{{item.name}}
	</li>
</transition-group>
<style>
	.v-enter,
	.v-leave-to
	{
	    opacity: 0;
	    transform: translateY(100px);
	}
	
	.v-enter-active,
	.v-leave-active
	{
	    transition: all 0.4s ease;
	}
</style>

然而 此时删除的时候 被删除的那条数据往下渐变消失
但在移动的过程中还是占着位置 直到全部消失 下面的数据才会填上去

此时 v-movev-leave-active配合使用 实现列表后续元素渐渐上移的效果
下面的数据也同步往上移动 占据被删除的数据的位置

<style>
	/* 在元素改变定位的过程中应用 */
	.v-move
	{
	    transition: all 0.4s ease;
	}
	.v-leave-active
	{
	    position: absolute;
	}
</style>

此时 由于为v-leave-active设置了position: absolute
被删除的数据在渐变消失的过程中 宽度会异常缩小
解决方法也很简单 给li设置个宽度即可

<style>
	li
	{
		width: 100%;
	}
</style>

3、初始动画

除此之外 还可实现刚加载进入页面时 所有列表渐变移动进入的效果
<transition-group>标签加个appear属性即可 其它什么都不用设置

<transition-group appear>
	<li v-for="(item,i) in list" v-bind:key="item.id" @click="del(i)">
		编号:{{item.id}} === 姓名:{{item.name}}
	</li>
</transition-group>

4、<transition-group>标签的渲染

Vue默认会将<transition-group>标签渲染成一个<span>标签
即 代码里明明写的是<transition-group>标签 然鹅在页面上显示的是<span>标签

可在<transition-group>标签上添加tag属性 指定要渲染成的元素
若不指定 则会默认渲染成span标签

例:
tag=“ul” 意为 指定将<transition-group>渲染成一个ul标签

<transition-group appear tag="ul">
	<li v-for="(item,i) in list" v-bind:key="item.id" @click="del(i)">
		编号:{{item.id}} === 姓名:{{item.name}}
	</li>
</transition-group>

上一篇:「csp模拟」模拟测试1


下一篇:Vue中的css动画