👉 Vue3 路由动画怎么做才"丝滑"?从原理到工程实现,一次讲透 @giszhc/vue-page-motion
很多 Vue 项目一到"页面切换动画",就开始变味:
要么是生硬闪切
要么是 transition 写一半就摆烂
要么 KeepAlive 一加直接乱套 😅
今天我们用一个真实工程组件 ------ @giszhc/vue-page-motion,把"页面切换动画"这件事彻底讲明白。
在线示例
我们提供了一个功能完整的在线演示页面,您可以直接在浏览器中体验所有功能:
🌐 立即体验: 点击访问在线演示
1. 问题背景(真实场景)
在一个后台系统 / GIS 平台 / 中后台管理系统里,你一定见过这种需求:
- 页面切换要有左右滑动效果
- 返回上一页要"反向动画"
- 某些页面需要禁用动画(比如地图页)
- 页面状态要保持(表单不能丢)
👉 结果就是:
Vue Router + Transition + KeepAlive = 经典三体问题 ☠️
稍微写错一点,就会出现:
- 页面"闪一下"
- 动画方向错乱
- 缓存页面不更新
- 路由切换卡顿
2. 核心问题(本质分析)
问题本质其实就三个:
❗ 1. 路由状态 ≠ UI状态
Vue Router 只负责跳转,不负责动画语义。
❗ 2. Transition 只认识"进入/离开"
但不知道:
- 是前进还是后退
- 是栈变化还是 replace
- 是用户意图还是系统跳转
❗ 3. KeepAlive 会"冻结组件"
导致动画和生命周期错位。
3. 原理讲解(核心设计思想)
@giszhc/vue-page-motion 本质做了三件事:
✔ ① 路由栈方向识别
判断 forward / back
✔ ② 动画策略抽象
支持:
- 固定动画
- 函数动态动画
- route.meta 控制
✔ ③ KeepAlive 解耦
动画和缓存不再互相污染
👉 关键思想一句话:
"动画不应该由组件决定,而应该由路由语义驱动。"
4. 常见错误或误区
❌ 误区1:直接写 transition wrapper
很多人这样写:
html
<transition name="slide-left">
<router-view />
</transition>
问题:
- 永远一个方向
- back 行为错误
- 无法扩展策略
❌ 误区2:KeepAlive 全局开启
结果:
- 表单不刷新
- 页面状态"鬼畜残留"
❌ 误区3:动画和路由耦死
写在组件里 = 后期维护灾难
5. 解决方案(分层设计)
我们把系统拆成三层:
🧠 路由层
判断 forward / back
🎬 动画层
transition strategy
🧩 渲染层
TransitionRouterView
6. 工程实现(核心代码)
✔ 安装
bash
pnpm install @giszhc/vue-page-motion
✔ 基础使用
html
<template>
<TransitionRouterView />
</template>
<script setup>
import { TransitionRouterView } from '@giszhc/vue-page-motion'
import '@giszhc/vue-page-motion/dist/index.css'
</script>
✔ 插件方式(推荐)
js
import { createApp } from 'vue'
import App from './App.vue'
import VuePageMotion from '@giszhc/vue-page-motion'
import '@giszhc/vue-page-motion/dist/index.css'
createApp(App)
.use(VuePageMotion)
.mount('#app')
✔ KeepAlive 实战(踩坑重点)
vue
<TransitionRouterView
:keep-alive="true"
:include="['Home', 'About']"
/>
👉 真实坑点:
- include 名称必须是组件 name
- 不然缓存"完全失效但不报错"
这类问题最折磨人 😅
✔ 动画策略(核心亮点)
1️⃣ 固定动画
vue
<TransitionRouterView transition="slide-left" />
2️⃣ 动态函数(工程常用)
js
const getTransition = (route, direction) => {
if (route.meta.noAnimation) {
return ''
}
return direction === 'forward'
? 'slide-left'
: 'slide-right'
}
vue
<TransitionRouterView :transition="getTransition" />
👉 适用于:
- GIS地图页禁动画
- 表单页弱动画
- dashboard 强动画
3️⃣ route.meta 驱动(最优雅)
js
{
path: '/special',
component: SpecialPage,
meta: {
transition: 'slide-right'
}
}
8. 性能 & 优化建议
⚡ 1. 避免全量 KeepAlive
只缓存高频页面:
js
include: ['Home', 'Dashboard']
如果这篇文章对你有帮助,欢迎点赞 👍 收藏 ⭐ 关注 👀
完结,撒花✿✿ヽ(°▽°)ノ✿