各位客官,里边请!今天咱就来聊聊 Vue Router 里的花式过场动画,保证让你的页面切换不再干巴巴,而是充满艺术气息!
开场白:动画,让你的 Vue 应用活起来!
话说,一个好的用户体验,除了功能强大,界面美观,还少不了那么一点点的“小心机”—— 动画!页面切换时的生硬跳转,就像是突然断电一样,让人感觉很突兀。而流畅自然的过渡动画,则像是加了润滑剂,让整个应用体验更加丝滑。
Vue Router 本身就提供了 <transition>
组件,方便我们添加过渡效果。但要做出真正惊艳的动画,还得咱们自己动手,丰衣足食。
第一节课:Vue Router 过渡动画的基础知识
首先,咱们得搞清楚 Vue Router 和 <transition>
组件是如何配合工作的。简单来说,当路由切换时,<transition>
组件会包裹住被切换的组件,然后根据路由的变化,自动添加和移除 CSS 类名,触发 CSS Transitions 或 Animations。
几个关键的 CSS 类名:
类名 | 描述 |
---|---|
v-enter-from |
定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。 |
v-enter-active |
定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义过渡的过程时间,延迟和曲线函数。 |
v-enter-to |
定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter-from 被移除),在过渡/动画完成之后移除。 |
v-leave-from |
定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。 |
v-leave-active |
定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义过渡的过程时间,延迟和曲线函数。 |
v-leave-to |
定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave-from 被移除),在过渡/动画完成之后移除。 |
这些类名中的 v-
前缀,默认是 transition
组件的 name
属性。如果你的 name
属性是 "fade",那么类名就会变成 fade-enter-from
、fade-enter-active
等等。
最简单的例子:淡入淡出
<template>
<router-view v-slot="{ Component }">
<transition name="fade" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
</template>
<style scoped>
.fade-enter-from {
opacity: 0;
}
.fade-enter-active {
transition: opacity 0.3s ease;
}
.fade-enter-to {
opacity: 1;
}
.fade-leave-from {
opacity: 1;
}
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-leave-to {
opacity: 0;
}
</style>
这段代码实现了一个简单的淡入淡出效果。mode="out-in"
的作用是先执行离开动画,再执行进入动画,避免页面内容重叠。
第二节课:更高级的过渡效果—— CSS Transitions
仅仅是淡入淡出,显然满足不了我们追求极致的心。接下来,咱们来玩点更高级的,利用 CSS Transitions 实现更丰富的过渡效果。
从左到右滑入滑出
<template>
<router-view v-slot="{ Component }">
<transition name="slide-left" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
</template>
<style scoped>
.slide-left-enter-from {
transform: translateX(100%); /* 从右边进入 */
opacity: 0;
}
.slide-left-enter-active {
transition: all 0.3s ease;
}
.slide-left-enter-to {
transform: translateX(0);
opacity: 1;
}
.slide-left-leave-from {
transform: translateX(0);
opacity: 1;
}
.slide-left-leave-active {
transition: all 0.3s ease;
position: absolute; /* 关键:脱离文档流,避免影响其他元素 */
width: 100%; /* 关键:保证宽度 */
}
.slide-left-leave-to {
transform: translateX(-100%); /* 从左边离开 */
opacity: 0;
}
</style>
这个例子利用了 transform: translateX()
属性,实现了从左到右的滑入滑出效果。 注意 position: absolute
和 width: 100%
的设置,这两个属性非常重要,可以避免离开的元素影响进入的元素。
注意事项:
position: absolute
:让离开的元素脱离文档流,避免挤压进入的元素。width: 100%
:保证离开的元素占据整个容器的宽度,避免出现动画异常。
第三节课:让动画更炫酷—— CSS Animations
CSS Transitions 虽然方便,但有些复杂的动画效果,用 Transitions 实现起来就比较吃力。这时候,CSS Animations 就能派上用场了!
放大缩小旋转
<template>
<router-view v-slot="{ Component }">
<transition name="scale-rotate" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
</template>
<style scoped>
@keyframes scale-rotate-enter {
from {
transform: scale(0) rotate(360deg);
opacity: 0;
}
to {
transform: scale(1) rotate(0deg);
opacity: 1;
}
}
@keyframes scale-rotate-leave {
from {
transform: scale(1) rotate(0deg);
opacity: 1;
}
to {
transform: scale(0) rotate(-360deg);
opacity: 0;
}
}
.scale-rotate-enter-active {
animation: scale-rotate-enter 0.5s ease;
}
.scale-rotate-leave-active {
animation: scale-rotate-leave 0.5s ease;
position: absolute;
width: 100%;
}
</style>
这个例子利用了 @keyframes
定义了两个动画:scale-rotate-enter
和 scale-rotate-leave
。 然后,在 .scale-rotate-enter-active
和 .scale-rotate-leave-active
中分别应用这两个动画。
CSS Animations 的优势:
- 更强的控制力: 可以精确控制动画的每一个关键帧。
- 更复杂的效果: 可以实现 Transitions 难以实现的复杂动画效果。
第四节课:动态过渡——根据路由变化选择动画
有时候,我们希望根据不同的路由,应用不同的过渡效果。比如,从 A 页面到 B 页面使用滑入动画,而从 B 页面到 C 页面使用淡入淡出动画。
实现思路:
- 在路由配置中,为每个路由添加一个
meta
字段,用于指定过渡动画的名称。 - 在
<transition>
组件中,动态绑定name
属性,根据当前路由的meta
字段来选择动画。
代码示例:
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/Home.vue'),
meta: {
transitionName: 'slide-left'
}
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue'),
meta: {
transitionName: 'fade'
}
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
<template>
<router-view v-slot="{ Component }">
<transition :name="transitionName" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
</template>
<script>
import { computed } from 'vue'
import { useRoute } from 'vue-router'
export default {
setup() {
const route = useRoute()
const transitionName = computed(() => route.meta.transitionName || 'fade') // 默认使用 fade 动画
return {
transitionName
}
}
}
</script>
<style scoped>
/* 之前的 slide-left 和 fade 动画样式 */
.slide-left-enter-from {
transform: translateX(100%);
opacity: 0;
}
.slide-left-enter-active {
transition: all 0.3s ease;
}
.slide-left-enter-to {
transform: translateX(0);
opacity: 1;
}
.slide-left-leave-from {
transform: translateX(0);
opacity: 1;
}
.slide-left-leave-active {
transition: all 0.3s ease;
position: absolute;
width: 100%;
}
.slide-left-leave-to {
transform: translateX(-100%);
opacity: 0;
}
.fade-enter-from {
opacity: 0;
}
.fade-enter-active {
transition: opacity 0.3s ease;
}
.fade-enter-to {
opacity: 1;
}
.fade-leave-from {
opacity: 1;
}
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-leave-to {
opacity: 0;
}
</style>
这段代码实现了根据路由 meta
字段动态选择过渡动画的效果。
第五节课:性能优化——硬件加速与防抖
动画效果虽好,但也不能贪多嚼不烂。过多的动画,或者复杂的动画,可能会影响应用的性能。所以,我们需要对动画进行一些优化。
1. 硬件加速
尽量使用 transform
和 opacity
属性来实现动画,因为这两个属性可以利用 GPU 进行硬件加速,从而提高动画的性能。
2. 防抖(Debounce)
如果你的动画触发频率很高,比如滚动事件触发的动画,可以考虑使用防抖技术,减少动画的执行次数。
function debounce(func, delay) {
let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), delay);
};
}
举个栗子:
<template>
<div @scroll="handleScroll">
<!-- 内容 -->
</div>
</template>
<script>
import { debounce } from './utils'; // 假设 debounce 函数在 utils.js 文件中
export default {
mounted() {
this.handleScroll = debounce(this.handleScroll, 250); // 250ms 防抖
},
methods: {
handleScroll() {
// 滚动事件处理逻辑,触发动画
console.log('Scrolling...');
}
}
}
</script>
第六节课:避免常见的坑
mode="out-in"
的坑: 如果你的页面内容高度不固定,mode="out-in"
可能会导致页面闪烁。可以尝试使用mode="in-out"
,或者调整动画效果,避免页面高度变化过大。position: absolute
的坑: 如果使用了position: absolute
,一定要保证父元素有明确的高度,否则可能会导致页面布局错乱。overflow: hidden
的坑: 如果父元素设置了overflow: hidden
,可能会导致动画效果被裁剪。
总结:动画,是提升用户体验的一把利器!
今天咱们学习了如何在 Vue Router 中实现自定义的导航过渡效果,以及如何利用 CSS Transitions 和 Animations 来优化动画效果。 记住,动画不是越多越好,而是要恰到好处,让你的应用更加生动有趣!
课后作业:
- 尝试实现一个更复杂的过渡动画效果,比如 3D 旋转或者翻页效果。
- 为你的 Vue 应用添加动态过渡效果,根据不同的路由选择不同的动画。
- 使用性能分析工具,测试你的动画效果,并进行优化。
好了,今天的课程就到这里。希望大家学有所获,做出更棒的 Vue 应用! 下课!