vueRouter路由切换时实现页面子元素动画效果, 左右两侧滑入滑出效果
说明
vue路由切换时,当前页面左侧和右侧容器分别从两侧滑出,新页面左右分别从两侧滑入
效果展示
路由切换-滑入滑出效果
难点和踩坑
- 现路由和新路由始终存在一个页面根容器,通过
<transition>
组件,效果只能对页面根容器有效。 - 如果通过组件(页面)级路由守卫(进入、退出)来改变受控变量,模版对左右容器v-if +
<transition>
设置效果。- 路由切换是一瞬间的事,滑出动画来不及触发,路由就改变了
- 所有页面都需要改造
- 我确实没找到路由守卫进入事件 只有
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
- 如果纯通过onMounted和onUnMounted等钩子实现,和2的问题基本差不多
实现方式
基于<template>
组件的钩子函数完全自主实现过渡效果.
钩子函数 | 说明 |
---|---|
beforeEnter | 在元素被插入到 DOM 之前被调用 |
enter | 在元素被插入到 DOM 之后的下一帧被调用 |
afterEnter | 当进入过渡完成时调用。 |
enterCancelled | 当进入过渡在完成之前被取消时调用 |
beforeLeave | 在 leave 钩子之前调用, 大多数时候,你应该只会用到 leave 钩子 |
leave | 在离开过渡开始时调用 |
afterLeave | 在离开过渡完成, 且元素已从 DOM 中移除时调用 |
leaveCancelled | 仅在 v-show 过渡中可用 |
直接上代码
<router-view>
改造
<router-view v-slot="{ Component }">
<transition
mode="default"
:css="false"
@before-leave="onBeforeLeave"
@before-enter="onBeforeEnter"
@enter="onEnter"
@leave="onLeave"
>
<component :is="Component"></component>
</transition>
</router-view>
钩子函数
/**
* left-wrap和right-wrap 为路由页面中左右两侧模块
*/
// 退出前的钩子
const onBeforeLeave = (el: any) => {
const left = el.querySelector('.left-wrap')
const right = el.querySelector('.right-wrap')
if (!left || !right) {
return
}
left.style.transform = 'translateX(0)'
right.style.transform = 'translateX(0)'
}
// 退出时的钩子
const onLeave = (el: any, done: Function) => {
const left = el.querySelector('.left-wrap')
const right = el.querySelector('.right-wrap')
if (!left || !right) {
done()
return
}
left.style.transition = 'all 0.3s linear'
right.style.transition = 'all 0.3s linear'
left.style.transform = 'translateX(-120%)'
right.style.transform = 'translateX(120%)'
/**
* 这里延迟done是为了过渡效果完成后再彻底退出
* 如果将时长改大一点, 页面审查元素就能看到,
* 路由切换时, 当前路由和新路由同时存在于页面, 当定时结束,done被调用时, 原路由组件才消失
*/
setTimeout(() => {
done() // 完成过渡
}, 300)
}
// 进入前的钩子
const onBeforeEnter = (el: any) => {
const left = el.querySelector('.left-wrap')
const right = el.querySelector('.right-wrap')
if (!left || !right) {
return
}
left.style.transform = 'translateX(-120%)'
right.style.transform = 'translateX(120%)'
}
// 进入时的钩子
const onEnter = (el: any, done: Function) => {
const left = el.querySelector('.left-wrap')
const right = el.querySelector('.right-wrap')
if (!left || !right) {
done()
return
}
left.style.transition = 'all 0.5s linear'
right.style.transition = 'all 0.5s linear'
// 这里延时是为了等待原路由退出效果完成, 再为新路由组件设置进入效果
setTimeout(() => {
left.style.transform = 'translateX(0)'
right.style.transform = 'translateX(0)'
done() // 完成过渡
}, 300)
}
总计
- 多调整参数看效果,就能大概猜出transition组件的实现原理
- 通过钩子函数自定义过渡或动画效果,可操作性确实大,就是有点麻烦