Vue 新手学习笔记:动画效果
1.过渡类名实现动画
参考:单元素/组件的过渡
-
v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
-
v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
-
v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时
v-enter
被移除),在过渡/动画完成之后移除。 -
v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
-
v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
-
v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时
v-leave
被删除),在过渡/动画完成之后移除。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./lib/vue-2.4.0.js"></script>
<style>
/* v-enter 是元素进入的起始状态,此时还没进入 */
/* v-leave-to 是动画离开之后,离开的终止状态,此时元素动画已经结束 */
.v-enter,.v-leave-to{
opacity: 0;
/* x 轴偏移 150px */
transform: translateX(150px)
}
/* v-enter-active 是入场动画的时间段 */
/* v-leave-active 是离场动画的时间段 */
.v-enter-active,
.v-leave-active{
/* all 表示所有元素,0.8s 是持续时间,ease 是动画效果 */
transition: all 0.8s ease;
}
/* 自定义 */
.my-enter,.my-leave-to{
opacity: 0;
transform: translateY(200px)
}
.my-enter-active,
.my-leave-active{
transition: all 0.8s ease;
}
</style>
</head>
<body>
<div id="app">
<input type="button" value="动画" @click="flag=!flag">
<!-- 需求:点击按钮,让h3显示,再点击让h3隐藏 -->
<!-- 1.使用 tansition 元素,把需要被动画控制的元素包起来 -->
<!-- transition 是 Vue 官方提供的 -->
<transition>
<h3 v-if="flag">这是一个H3</h3>
</transition>
<hr>
<!-- 自定义 transition 名字 -->
<input type="button" value="动画" @click="flag2=!flag2">
<transition name="my">
<h1 v-if="flag2">这是一个H1</h1>
</transition>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
flag: false,
flag2: false,
},
methods: {},
})
</script>
</body>
</html>
2.通过引入第三方类库来实现动画
- 通过对应特性来引入第三方类库
参考:自定义过渡的类名 - 通过 :duration 来设定效果持续的时间
这里以 Animate 为例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./lib/vue-2.4.0.js"></script>
<link rel="stylesheet" href="./lib/animate.css">
</head>
<body>
<div id="app">
<input type="button" value="动画" @click="flag=!flag">
<!-- <transition enter-active-class="animated bounceIn"
leave-active-class="animated bounceOut">
<h1 v-if="flag">这是一个H1</h1>
</transition> -->
<!-- :duration 可以放在 transition 上,也可以放在标签上 -->
<!-- 使用 :duration="毫秒值" 来统一设置入场和离场时候的动画时长 -->
<!-- <transition enter-active-class="bounceIn"
leave-active-class="bounceOut" :duration="200">
<h1 v-if="flag" class="animated">这是一个H1</h1>
</transition> -->
<!-- 通过传入对象,分别设置入场的时长和离场的时长 -->
<transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="{ enter:200, leave:800 }">
<h1 v-if="flag" class="animated">这是一个H1</h1>
</transition>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
flag: false,
},
methods: {},
})
</script>
</body>
</html>
3.使用钩子函数来实现动画
使用上面的两种方式,都只能够实现整场动画,我也奇怪,所以我试过在上面的函数中把后半场动画的函数去掉,比如上面 2 中 这个H1 动画,当我把后半场动画的代码去掉后,第一次点击出现了前半场动画效果,然后第二次点击,文字消失,第三次点击才会再次出现动画效果,所以为了实现半场动画效果就有了钩子函数来实现
钩子函数参考:JavaScript 钩子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./lib/vue-2.4.0.js"></script>
<link rel="stylesheet" href="./lib/animate.css">
<style>
.ball{
width: 15px;
height: 15px;
border-radius: 50px;
background-color: red;
}
</style>
</head>
<body>
<div id="app">
<input type="button" value="快到碗里来" @click="flag=!flag">
<!-- 使用 transition 把 div 包起来 -->
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter">
<div class="ball" v-show="flag"></div>
</transition>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
flag: false,
},
methods: {
//注意:钩子函数的第一个参数 el 表示要执行动画的那个元素,是个原生的 JS DOM 对象
//可以认为, el 是通过 document.getElementById('') 方式获取的原生的 JS DOM 对象
beforeEnter(el) {
//表示动画入场之前,此时动画尚未开始,可以设置元素开始动画之前的起始样式
//设置小球开始动画之前的起始位置
el.style.transform = "translate(0, 0)"
},
enter(el, done) {
//这句话,没有实际的作用,但是如果不写,出不来动画效果
//可以认为 el.offsetWidth 会强制动画刷新
el.offsetWidth;
//表示动画开始之后的样式,这里可以设置小球完成动画之后的结束状态
el.style.transform = "translate(150px, 450px)";
el.style.transition = 'all 1s ease';
//这里的 done,其实就是 afterEnter 函数,也就是说:done 是 afterEnter 函数的引用
done();
},
afterEnter(el) {
//动画完成之后调用
this.flag=!this.flag;
}
},
})
</script>
</body>
</html>
4.实现列表的动画效果
-
在需要使用列表过渡时候,如果过渡的元素是使用 v-for 循环出来的时候,应该使用 transition-group 代替 transition
-
在实现列表移除的效果时候,可以通过 .v-move 和 v-leave-active 配合使用,能够实现列表后续的动画元素
-
给 transition-group 添加 appear 可以添加页面刚展示出来的时候的入场效果
-
使用为 transition-group 设置 tag 属性,指定 transition-group 渲染为某个元素,如果不设置,默认渲染为 span 元素
比如下面代码中,如果不使用 tag 属性,而是直接使用 ul 标签,那么在生成的列表中 ul 与 li 元素中间会多一层 span 标签,不符合 W3C 规范,也可能影响到代码的书写,甚至使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./lib/vue-2.4.0.js"></script>
<style>
li {
border: 1px dashed #999;
margin: 5px;
line-height: 35px;
padding-left: 5px;
font-size: 12px;
width: 100%;
}
li:hover {
background-color: gold;
transition: all 1s ease;
}
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateY(80px)
}
.v-enter-active,
.v-leave-active {
transition: all 1s ease;
}
/* 下面的 .v-move 和 v-leave-active 配合使用,能够实现列表后续的元素,渐渐地漂上来的效果 */
.v-move{
transition: all 1s ease;
}
.v-leave-active {
position: absolute;
}
</style>
</head>
<body>
<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" value="添加" @click="add">
</div>
<!-- <ul> -->
<!-- 在需要使用列表过渡时候,如果过渡的元素是使用 v-for 循环出来的,则不能使用 transition -->
<!-- 应该使用 transition-group -->
<!-- 给 transition-group 添加 appear 可以添加页面刚展示出来的时候的入场效果 -->
<!-- 使用为 transition-group 设置 tag 属性,指定 transition-group 渲染为某个元素,如果不设置,默认渲染为 span 元素 -->
<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>
<!-- </ul> -->
</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
});
this.id = this.name = '';
},
del(i){
this.list.splice(i,1);
},
},
})
</script>
</body>
</html>