Для того щоб нормально реалізувати анімацію переходів між сторінками з Slide Left Right transition вам потрібно виконати декілька кроків.
Як я пропоную це реалізувати, без додаткових записів в router.js, без додаткових міток на сторінках, все на автопілоті.
Для цього вам потрібно нормалізувати ваш файл router.js, а саме правельно простроїти порядок маршрутів. Тобто у нас є сторінка припустимо головна /
, вона стоїть в списку перша, тому індекс у неї 1. Наступний роут /wallet
записаний відразу після, тому індекс у нього 2, і так далі. Коли користувач буде переходити з /wallet
на /
, то він буде переходити з індексу 2 на 1, тоюто в нього буде спрацьовувати slide to left, якщо він будете переходити з 1 на 2, то slide to right. Якщо у роута є вкладеності, то там логіка така сама, але верхній індекс буде завжди більше, тому перехід з вкладиних роутів буде завжди назад. Приклад файла router.js
:
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/',
children: [
{
path: '',
name: 'home',
component: MainView,
},
{
path: 'wallets',
name: 'wallets',
component: WalletsView
},
{
path: 'support',
name: 'support',
component: SupportView
},
]
},
{
path: "/profile",
name: 'profile',
component: ProfileView
}
]
})
Теперь нам треба визначити індекси усіх роутів, включно з вкладеними, з цього всього створити масив, та звіряти роути на які буде переходити користувач, для того щоб застосувати потрібну анімацію слайд вліво чи вправо. Для цього пропоную використати рекурсивну функцію:
const route = useRoute()
const router = useRouter()
const routes = router.getRoutes()
const transitionName = ref('default')
// рекурсивна функція для визначення індексів
function mapRoutesWithIndex(routes, basePath = '', index = '', map = {}) {
routes.forEach((route, idx) => {
const path = `${basePath}/${route.path}`.replace(/\/\/+/g, '/');
const currentIndex = index + idx.toString();
map[path] = currentIndex;
if (route.children && route.children.length > 0) mapRoutesWithIndex(route.children, path, currentIndex, map);
});
return map;
}
const routesIndexMap = mapRoutesWithIndex(routes);
В routesIndexMap
ми отримуюмо карту індексів роутів, теперь треба її тільки звірити, та застосувати:
router.afterEach((to, from) => {
window.scrollTo({
top: 0,
behavior: "smooth"
})
const toIndex = routesIndexMap[to.fullPath] || 0;
const fromIndex = routesIndexMap[from.fullPath] || 0;
transitionName.value = toIndex > fromIndex ? 'slide-left' : 'slide-right';
})
Чудово, якщо ви все зробили правельно, то визначення напрямку буде працювати корректно.
Тепер додамо анімацію в наш App.vue:
<template lang="pug">
.g
RouterView(v-slot="{ Component }")
transition(:name="transitionName" )
component(:is="Component")
</template >
<script setup>
const route = useRoute()
const router = useRouter()
const routes = router.getRoutes()
const transitionName = ref('default')
function mapRoutesWithIndex(routes, basePath = '', index = '', map = {}) {
routes.forEach((route, idx) => {
const path = `${basePath}/${route.path}`.replace(/\/\/+/g, '/');
const currentIndex = index + idx.toString();
map[path] = currentIndex;
if (route.children && route.children.length > 0) mapRoutesWithIndex(route.children, path, currentIndex, map);
});
return map;
}
const routesIndexMap = mapRoutesWithIndex(routes);
router.afterEach((to, from) => {
window.scrollTo({
top: 0,
behavior: "smooth"
})
const toIndex = routesIndexMap[to.fullPath] || 0;
const fromIndex = routesIndexMap[from.fullPath] || 0;
transitionName.value = toIndex > fromIndex ? 'slide-left' : 'slide-right';
})
</script>
<style lang="stylus">
.slide-right-enter-active, .slide-right-leave-active, .slide-left-enter-active, .slide-left-leave-active
transition: all 0.25s ease;
position fixed
top 0
width 100%
left 0
.slide-left-leave-to
opacity: 0;
transform translateX(-100%)
.slide-left-enter-from
opacity: 0;
transform translateX(100%)
.slide-right-leave-to
opacity: 0;
transform translateX(100%)
.slide-right-enter-from
opacity: 0;
transform translateX(-100%)
</style>
Зверніть увагу, що в мене в момент transition, сторінка переходить в position fixed, ви це можете выдмінити, змінив ти анімації на out-in. Але для мене потрібно було саме так. На цьому все, дякую за увагу.