Анімація page transition slide left right Vue3

Для того щоб нормально реалізувати анімацію переходів між сторінками з 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. Але для мене потрібно було саме так. На цьому все, дякую за увагу.