一、动画实现方式
在Vue中 有三种动画的实现方式 分别是:
- 使用过渡类名实现
- 使用第三方animate.css实现
- 使用钩子函数实现
下面将一一介绍:
1、使用过渡类名实现
首先 来了解一下动画的过渡类名:
( 这是我在Vue官网找到的一个示意图 )
动画 实际上是分成了[ 进入 ]和[ 离开 ]这两部分
每个动画有两个时间点和一个时间段
例如 对于进入(Enter)动画:
两个时间点是v-enter和v-enter-to
一个时间段是v-enter-active
进入 是一个半场动画
退出 也是一个半场动画
两个半场动画组成了一个完整的动画
v-enter
和v-leave-to
样式是未激活样式 可视为一组v-enter-to
和v-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-move和v-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>