1、利用transition标签进行实现(Vue3 )。
官方说明地址:https://cn.vuejs.org/guide/built-ins/transition
<template>
<router-view v-slot="{ Component }">
<transition name="fade">
<component :is="Component" />
</transition>
</router-view>
</template>
<style scoped lang="less">
/* 路由切换动画 */
//官网地址:https://cn.vuejs.org/guide/built-ins/transition
/* fade-transform */
.fade-leave-active,
.fade-enter-active {
transition: all 0.5s;
}
.fade-enter-from {
opacity: 0;
transform: translateY(-30px);
}
.fade-enter-to {
opacity: 1;
transform: translateY(0px);
}
.fade-leave-to {
opacity: 0;
transform: translateY(30px);
}
</style>
2、路由前置守卫执行动画
router_animate.js 文件
//路由跳转动画
const body = document.body
//背景板块个数
const num = 9
//动画执行时间(s),要与css中的animate动画(router_top 、router_bottom)保持一致,如动画是0.5s,那么time最多是1,最少是0.7,没有具体数值规律 !!!!
const time = 1
//返回promise对象
const router_animate = () => {
return new Promise((succ, fail) => {
const div = document.createElement("div")
if (!div) {
fail({ type: 'error', msg: "页面未完全渲染" })
}
div.classList.add("vue_router")
for (let i = 0; i < num; i++) {
const list = document.createElement("div")
list.classList.add("vue_router_list")
list.style.backgroundPositionX = `-${i / num * 100}vw `
div.appendChild(list)
}
body.appendChild(div)
//留下time * (1000 -800)的时间来渲染下次路由页面
//time变量的更改请看上面介绍
setTimeout(() => {
body.removeChild(div)
}, time * 1000);
setTimeout(() => {
succ()
}, time * 800);
})
}
export default router_animate
router/index.js 文件
import { createRouter, createWebHistory } from 'vue-router'
import index from "@pages/index/index.vue"
import router_animate from './router_animate.js'
const routes = [
{
path: '/',
component: index
},
]
const router = createRouter({
history: createWebHistory(),
routes
})
router.beforeEach((to, from, next) => {
//路由动画效果
router_animate().then(res => {
next()
})
})
export { router }
全局css文件
style.css
<style>
//css文件,不需要style标签,我加标签仅仅是为了csdn的高亮效果
//此文件需要再main.js全局引入
/* 路由跳转动画 */
.vue_router {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: 999;
display: flex;
animation: router_opacity 1s ease-in-out forwards;
/* background-color: #000; */
}
.vue_router_list {
flex-grow: 1;
//随便找一张图,没有就去掉
background: url('@/assets/images/loading.png') no-repeat;
/* background-color: #000; */
background-size: 100vw auto;
}
.vue_router_list:nth-child(odd) {
animation: router_top .5s ease-in-out forwards;
}
.vue_router_list:nth-child(even) {
animation: router_bottom .5s ease-in-out forwards;
}
@keyframes router_top {
0% {
transform: translateY(-100%);
opacity: 0;
}
100% {
transform: translateY(0%);
opacity: 1;
}
}
@keyframes router_bottom {
0% {
transform: translateY(100%);
opacity: 0;
}
100% {
transform: translateY(0%);
opacity: 1;
}
}
@keyframes router_opacity {
0% {
opacity: 1;
width: 100%;
}
80% {
opacity: 1;
width: 100%;
}
100% {
opacity: 0;
width: 0%;
}
}
</style>
main.js
import { createApp } from 'vue'
import App from './App.vue'
//全局引入css文件
import './style.css'
import { router } from './router/index'
// ...
// ...
const app = createApp(App)
app.use(router).mount('#app')