VUE路由切换页面自定义动画效果

效果演示

使用的API和类库

Transitionrouter-view
可选:keep-alivepinia

关键代码

<template>
<router-view v-slot="{ Component }">
    <transition :name="transitionName">
        <component :is="Component" />
    </transition>
</router-view>
</template>
<script setup>
import { ref } from 'vue'
const transitionName=ref('')
window.will_push = () => {
  transitionName.value='forward'
}
window.will_back = () => {
  transitionName.value='back'
}
</script>
<style>
/* ================= 前进动画 ================= */
/* 进入的元素动画执行时样式 */
.forward-enter-active {

}
/* 进入的元素动画初始样式 */
.forward-enter-from {

}
/* 进入的元素动画结束时样式 */
.forward-enter-to {

}
/* 离开的元素动画执行时样式 */
.forward-leave-active {

}
/* 离开的元素动画初始样式 */
.forward-leave-from {

}
/* 离开的元素动画结束时样式 */
.forward-leave-to {

}

/* ================= 后退动画 ================= */
/* 进入的元素动画执行时样式 */
.back-enter-active {

}
/* 进入的元素动画初始样式 */
.back-enter-from {

}
/* 进入的元素动画结束时样式 */
.back-enter-to {

}
/* 离开的元素动画执行时样式 */
.back-leave-active {

}
/* 离开的元素动画初始样式 */
.back-leave-from {

}
/* 离开的元素动画结束时样式 */
.back-leave-to {

}
</style>

关于样式的定义

设置、触发动画的方法

在需要添加动画的路由切换时,先调用window.will_push()window.will_back(),再调用router.push()router.back(),即可稳定、灵活地触发切换动画。

不在router.beforeEach中改变transitionName值的原因

触发路由跳转时的执行流程如下:

同步任务 (Tick 1):
↓ 用户点击路由链接 / router.push()
↓ beforeEach 守卫执行 ← 修改 ref(值变了,但 DOM 未更新)
↓ beforeRouteLeave 守卫
↓ beforeRouteEnter 守卫
↓ 路由确认完成

微任务队列 (Tick 1 结束后):
↓ transitionName 的响应式更新触发
↓ 计算属性重新计算
↓ 准备组件更新

下一个 Tick (Tick 2):
↓ <router-view> 开始卸载旧组件
↓ <Transition> 组件初始化,读取 props(包括 name)
↓ 此时才用到 transitionName 的"新值"

问题在于:Transition 可能在前一个 tick 就已经读取了旧值,或者更新时机与组件卸载/挂载不匹配。尤其是旧组件的退出动画,很可能不会正确执行。
贴别是配合使用keep-alive的情况

<router-view v-slot="{ Component }">
    <transition :name="transitionName">
        <keep-alive :include="pageKeepAlive.names">
            <component :is="Component" />
        </keep-alive>
    </transition>
</router-view>

实际使用中,很可能还要和keep-alive一并使用,并且keep-aliveinclude也需要动态绑定,这种情况更复杂。所以,完全手动控制transitionname,并在路由跳转开始前就修改好transitionName的值是一种比较稳妥的办法。为减少代码冗余,可以自行封装router.push等方法,预置transitionName即可。

其他需要注意的事项

  • window.will_push等挂载到全局上的方法,也可以使用pinia代替,transitionName使用计算属性即可。

  • 在动画样式中,如需要实现页面整体平移等transform,需要在v-enter-activev-leave-active中添加position: absolute !important,通过绝对定位控制位移动画。

  • 关于Transition的mode,官方文档中有说明,需要两个页面同时存在(进入和退出动画同时执行)的情况,mode无需设置保持默认即可,另外的情况按需修改。

  • useRoute()meta等响应式数据,会在路由切换最开始的那一刻就立即切换为新页面(to)的内容。如果你的项目中旧页面(from)中的某些元素或属性依赖了useRoute()中的信息,在路由切换开始时,可能会使旧页面的某些元素发生切换或闪烁,或触发预料外的逻辑,最好的办法是使用额外的变量储存初始化时的useRoute()中的信息,不要直接依赖useRoute()

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇