本文中所有的代码会在文末提供下载链接,觉得作者写的还行的话,给个赞把.
概述
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。
包括以下工具:
- 在 CSS 过渡和动画中自动应用 class
- 可以配合使用第三方 CSS 动画库,如 Animate.css
- 在过渡钩子函数中使用 JavaScript 直接操作 DOM
- 可以配合使用第三方 JavaScript 动画库,如 Velocity.js
演示
我们来看一下一个最基本的动画例子
分析
注意:插入、更新或者移除 DOM…只有在元素发生变化的时候才会触发动画
这里我们以v-if来模拟显示和隐藏举例
<style>
/*定义两组样式,来控制transition内部的元素实现动画*/
.v-enter ,.v-leave-to {
transform: translateX(200px);
opacity: 0;
}
.v-enter-active,.v-leave-active {
transition: all .5s ease;
}
</style>
</head>
<body>
<div id="app">
<button @click="flag=!flag">点击隐藏/显示</button>
<!--使用transition将需要被动画控制的元素包裹起来-->
<transition>
<h1 v-if="flag">演示文本</h1>
</transition>
</div>
<script>
var vm = new Vue({
el: "#app",
data:{
flag: false
},
methods:{
}
})
</script>
实现动画分三个步骤
- 用transition把需要做动画的元素(元素是即将要变化的例如插入删除,更新)包裹起来
- 定义v-enter,v-leave-to,(其实还有两个类,我们演示就用这两个)和.v-enter-active,.v-leave-active
- 让其元素发送变化(插入,删除, 更新),则会触发动画
在vue中动画分为四个状态和两个阶段(参见上面的css类)
四个状态分别为
- enter
- enter-to
- leave-to
- leave
四个状态
v-enter
指元素进入动画之前的样式
v-enter-to
指元素已经进入动画的样式
v-leave-to
指元素将要移除(更新)的之前的样式
v-leave-to
指元素已经移除(更新)的样式
两个阶段
两个状态分别指
- v-enter-active
- v-leave-active
*-enter-active
指在*-enter>>>>*-enter-to之间的样式一般我们会给其添加transition属性
v-leave-active
指在v-leave>>>>v-leave-to之间的样式一般我们会给其添加transition属性
以上就是一个非常基础的动画了,发现了吗?上面的2+4的类都是以v-开头的?如果我觉得这个前缀命名不好,想改名字可以吗?
是可以的;
怎么去自定义前面的前缀呢?
很简单只需要在transition标签上指定name属性的值即可,就像下面这样
<transition name="myPrefix">
<h1 v-if="flag">演示文本</h1>
</transition>
第三方类实现动画
有的人说,写个动画还要写这么多类,好烦呐,~~欸…烦就对了,vue官方知道大家都很懒,所以提供了第二种方法来实现动画,就是使用第三方的动画库,例如animate.css我们可以直接引用类库中的类去实现动画,是不是好多了.
那么具体到底如何实现呢?
<div id="app">
<input type="button" value="切换状态" @click="flag=!flag">
<!--在这里我们使用animate.css中的bounceIn和bounceOut这两个类
来实现动画,当然你可以选择其他的-->
<transition
class="animated"
:duration="{enter:200,leave:400}"
enter-active-class="bounceIn"
leave-active-class="bounceOut">
<h3 v-if="flag">测试文本</h3>
</transition>
</div>
<script>
var vm = new Vue({
el: "#app",
data:{
flag: false
},
methods:{
}
})
</script>
animated不会使用的话建议先看看相关文档
这时候步骤就变成了
- 引入animate.css
- 使用transition包裹需要做动画的元素
- 给transition添加
enter-active-class
和leave-active-class
这两个属性分别将其值指定为animate.css中相关的动画类//说明:enter-active-class指的是元素进入/更新时的样式-----leave-active-class则反之. - 细心的人发现了上面还有一个属性绑定的duration这个属性可以分别来指定进入动画的持续时间和出去时的持续时间
动画的钩子函数
动画的钩子函数,可以理解成动画的生命周期,从动画开始到动画结束.他们是以事件的形式存在的
分别是
动画进入时的钩子函数
- before-enter
- enter
- after-enter
动画离开时的钩子函数
- before-leave
- leave
- after-leave
接下来我们用钩子函数实现一个半场动画(只有enter没有leave)
<div id="app">
<button @click="flag=!flag">运动</button>
<!--给transition绑定动画enter钩子事件-->
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter">
<div class="ball" v-if="flag"></div>
</transition>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
flag: false
},
methods: {
//动画钩子函数
//注意:动画钩子函数的第一个参数el,表示要执行动画的那个dom元素,是个原生dom元素
beforeEnter(el) {
// 表示动画入场之前,此时,动画尚未开始,可以在beforeEnterz中设置元素开始动画之前的启示样式
el.style.transform = "translate(0,0)"
// 设置小球开始动画之前的起始位置
},
enter(el,done) {
//此处的done代表下一个钩子函数,在调用done之后会直接调用afterEnter函数(),不调用小球会延迟消失
//!!!!!这块tm是个大坑,必须加上才有动画。黑魔法
el.offsetLeft;//或者时offsetWidth||offsetHeight||offsetRight
//enter 表示动画开始之后的样式,这里可以设置小球完成动画之后的结束状态
el.style.transform = "translate(150px,450px)";
el.style.transition = "all 1s ease";
done()
},
afterEnter(el) {
//在执行完成之后小球会等一会消失
this.flag = !this.flag;
}
}
})
</script>
分析
以enter事件举例:
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter">
<div class="ball" v-if="flag"></div>
</transition>
我们给transition绑定了enter事件,处理函数时enter(其他名字也可以),
这里提一点:每个钩子函数中的处理函数中的第一个参数都是当前需要做动画的元素,enter和leave这两个钩子函数稍有不同,还有第二个参数,enter的第二个参数表示after-enter这个钩子的处理函数,leave的第二个参数表示after-leave这个钩子的处理函数
我们按照思路写好了,写成如下这样,会发现,动画呢???完全出不来啊!!!摔
enter(el,done) {
el.style.transform = "translate(150px,450px)";
el.style.transition = "all 1s ease";
done();
},
,查阅官方文档之后,原来需要给其**添加el.offsetLeft;**这样一条属性,果不其然,动起来了.
enter(el,done) {
el.offsetLeft;
el.style.transform = "translate(150px,450px)";
el.style.transition = "all 1s ease";
done();
},
以上就是使用vue实现一个半场的动画.
列表动画
实现了单个的元素的动画,需求时无止境的,比如现在有这样一个需求
有一个列表,初始化整个列表的时候,渐渐出现,添加单个列表项的时候让其渐渐显示出来,删除的时候也渐渐消失.
之后,用transition标签一同乱做,就是效果出不来,去官网查阅文档,发现在处理列表过渡的时候有一个专门的标签
transition-group于是乎,经过一顿踩坑之后…
先看看完成效果吧
first,我们先看看列表动画的必要条件
- 使用transition-group包裹列表项
- 定义.v-enter,.v-leave-to和.v-enter-active,.v-leave-active 类
- 被包裹的元素更新或删除
<div id="app">
<div>
<label>
id:
<input type="text" v-model="id">
</label>
<label>
name:
<input type="text" v-model="name">
</label>
<input type="button" @click="add">
</div>
<!--多个元素的过渡需要使用transition-group包裹起来-->
<!--如果要给v-for创建的元素设置动画,必须给每一个元素设置key属性-->
<!--给transition-group添加appear属性,实现页面刚展示出来的效果,入场时侯的效果-->
<!--transition-group会默认被渲染成span 我们可以通过tag指定要渲染的标签-->
<transition-group appear tag="ul">
<li v-for="(item,i) in list" :key="item.id" @click="del(i)">{{item.id}}-----{{item.name}}</li>
</transition-group>
</div>
<script>
var vm = new Vue({
el: "#app",
data:{
id: "",
name: "",
list:[
{id:1,name:"暗夜猎手"},
{id:2,name:"猎天使魔女"},
{id:3,name:"苍穹之光"},
{id:4,name:"源计划"},
]
},
methods:{
add() {
this.list.push({id:this.id, name: this.name})
},
del(i) {
this.list.splice(i, 1);
}
}
})
</script>