还在硬邦邦跳转页面?Vue这3招让应用丝滑如德芙!
你是不是也遇到过这种情况?页面切换生硬得像老式电视机换台,数据加载时用户一脸懵逼不知道发生了什么,列表操作毫无反馈让人怀疑到底点没点上...
别急!今天我就带你用Vue的过渡动画三招,让你的应用瞬间从"机械僵硬"变身"丝滑流畅",用户体验直接提升一个level!
第一招:基础CSS过渡,简单又高效
先来看看最基础的CSS过渡效果。Vue提供了 <transition>
组件,包裹一下就能让元素动起来!
<template>
<div>
<button @click="show = !show">切换显示</button>
<transition name="fade">
<p v-if="show">你好呀!我会淡入淡出哦~</p>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
show: true
}
}
}
</script>
<style>
/* 定义进入和离开时的动画 */
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s ease;
}
/* 定义进入开始和离开结束时的状态 */
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
这里有个小秘密:Vue会自动帮我们在不同阶段添加不同的 class:
fade-enter
:进入动画开始前(第一帧)fade-enter-active
:进入动画过程中fade-enter-to
:进入动画结束后fade-leave
:离开动画开始前fade-leave-active
:离开动画过程中fade-leave-to
:离开动画结束后
第二招:CSS动画,让效果更丰富
如果觉得简单的过渡不够酷,试试CSS动画吧!用法和过渡差不多,但能做出更复杂的效果。
<template>
<div>
<button @click="show = !show">蹦出来!</button>
<transition name="bounce">
<p v-if="show" class="animated-text">看我弹跳登场!</p>
</transition>
</div>
</template>
<style>
/* 弹跳动画 */
.bounce-enter-active {
animation: bounce-in 0.5s;
}
.bounce-leave-active {
animation: bounce-in 0.5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.25);
}
100% {
transform: scale(1);
}
}
.animated-text {
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
padding: 10px;
border-radius: 5px;
color: white;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
这个效果特别适合重要提示或者操作反馈,让用户一眼就能注意到!
第三招:列表过渡,让数据动起来
实际项目中我们经常要处理列表数据,<transition-group>
就是专门为列表设计的动画组件。
<template>
<div>
<button @click="addItem">添加项目</button>
<button @click="removeItem">删除项目</button>
<transition-group name="list" tag="ul">
<li v-for="item in items" :key="item.id" class="list-item">
{{ item.text }}
</li>
</transition-group>
</div>
</template>
<script>
export default {
data() {
return {
items: [
{ id: 1, text: '第一项' },
{ id: 2, text: '第二项' },
{ id: 3, text: '第三项' }
],
nextId: 4
}
},
methods: {
addItem() {
this.items.push({
id: this.nextId++,
text: `新项目 ${this.nextId}`
})
},
removeItem() {
this.items.pop()
}
}
}
</script>
<style>
.list-item {
transition: all 0.5s;
margin: 5px 0;
padding: 10px;
background: #f8f9fa;
border-left: 4px solid #4ecdc4;
}
.list-enter-active, .list-leave-active {
transition: all 0.5s;
}
.list-enter, .list-leave-to {
opacity: 0;
transform: translateX(30px);
}
/* 让删除的项目先收缩再消失 */
.list-leave-active {
position: absolute;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
注意这里有两个重点:一是必须给每个列表项设置唯一的 key
,二是 <transition-group>
默认渲染为 span
,可以用 tag
属性指定为其他标签。
进阶玩法:JavaScript钩子函数
有时候CSS动画满足不了复杂需求,这时候就需要JavaScript钩子出场了!
<template>
<div>
<button @click="show = !show">切换</button>
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@enter-cancelled="enterCancelled"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
@leave-cancelled="leaveCancelled"
>
<div v-if="show" class="js-box">JS控制的动画</div>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
show: false
}
},
methods: {
// 进入动画开始前
beforeEnter(el) {
el.style.opacity = 0
el.style.transform = 'scale(0)'
},
// 进入动画中
enter(el, done) {
// 使用requestAnimationFrame保证流畅性
let start = null
const duration = 600
function animate(timestamp) {
if (!start) start = timestamp
const progress = timestamp - start
// 计算当前进度(0-1)
const percentage = Math.min(progress / duration, 1)
// 应用动画效果
el.style.opacity = percentage
el.style.transform = `scale(${percentage})`
if (progress < duration) {
requestAnimationFrame(animate)
} else {
done() // 动画完成,调用done回调
}
}
requestAnimationFrame(animate)
},
// 进入动画完成后
afterEnter(el) {
console.log('进入动画完成啦!')
},
// 进入动画被中断
enterCancelled(el) {
console.log('进入动画被取消了')
},
// 离开动画相关钩子...
beforeLeave(el) {
el.style.opacity = 1
el.style.transform = 'scale(1)'
},
leave(el, done) {
// 类似的实现离开动画...
done()
}
}
}
</script>
<style>
.js-box {
width: 100px;
height: 100px;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
margin-top: 10px;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
JavaScript钩子虽然复杂一些,但是能实现任何你能想到的动画效果!
终极武器:集成第三方动画库
如果你想快速实现酷炫效果,又不想自己写太多CSS,那么第三方动画库就是你的最佳选择!
先安装Animate.css:
npm install animate.css
然后在项目中引入:
import 'animate.css'
使用起来超级简单:
<template>
<div>
<button @click="show = !show">来点炫酷的!</button>
<transition
enter-active-class="animate__animated animate__bounceIn"
leave-active-class="animate__animated animate__bounceOut"
>
<div v-if="show" class="demo-box">哇!好酷!</div>
</transition>
</div>
</template>
<style>
.demo-box {
width: 150px;
height: 150px;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
color: white;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
margin-top: 20px;
font-size: 18px;
font-weight: bold;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Animate.css提供了超多现成动画效果,比如:
animate__bounceIn
(弹跳进入)animate__fadeInUp
(淡入上浮)animate__flip
(翻转效果)animate__zoomIn
(缩放进入)
想要什么效果,换个class名就行了,简直是懒人福音!
实战技巧:避免这些常见坑
用了这么久Vue动画,我也踩过不少坑,分享几个实用技巧:
- 动画闪烁问题:在初始渲染时避免使用
v-if
,可以用v-show
或者通过CSS控制初始状态 - 列表动画优化:对于长列表,可以给
<transition-group>
设置tag="div"
,避免生成太多DOM节点 - 性能注意:尽量使用
transform
和opacity
做动画,这两个属性不会触发重排,性能更好 - 移动端适配:在移动端注意动画时长,
0.3s
左右比较合适,不要太长 - 减少同时动画:同一时间不要有太多元素做动画,会影响性能
总结
好了,今天分享了Vue过渡动画的四大招式:从基础的CSS过渡,到更丰富的CSS动画,再到处理列表的 <transition-group>
,最后是强大的JavaScript钩子和第三方库集成。
记住,好的动画不是为了炫技,而是为了提升用户体验。适当的动画能让用户知道发生了什么,引导注意力,让操作更有反馈感。