Transition при смене маршрутов

Vue Router тесно интегрируется с системой анимаций Vue, предоставляя возможность создавать плавные переходы при смене маршрутов. Для реализации анимаций используется компонент <transition> или <transition-group>, оборачивающий <router-view>.

<template>
  <transition name="fade" mode="out-in">
    <router-view />
  </transition>
</template>

Атрибут name и CSS-классы

Атрибут name в <transition> задаёт префикс для классов, которые Vue автоматически применяет в процессе анимации:

  • fade-enter-from — начальное состояние входящей компоненты
  • fade-enter-active — состояние, применяемое на протяжении всей анимации входа
  • fade-enter-to — конечное состояние входа
  • fade-leave-from — начальное состояние исходящей компоненты
  • fade-leave-active — состояние, применяемое на протяжении всей анимации выхода
  • fade-leave-to — конечное состояние выхода

Пример CSS-анимации:

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
  transform: translateY(20px);
}

.fade-enter-to,
.fade-leave-from {
  opacity: 1;
  transform: translateY(0);
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s ease, transform 0.3s ease;
}

Атрибут mode

mode определяет последовательность анимации при смене маршрутов:

  • out-in — сначала выполняется анимация выхода текущей компоненты, затем вход новой
  • in-out — сначала анимация входа новой компоненты, затем выход старой
<transition name="slide" mode="out-in">
  <router-view />
</transition>

Динамические переходы

Для реализации различных анимаций в зависимости от маршрута можно использовать вычисляемое свойство для определения имени перехода:

<script>
export default {
  computed: {
    transitionName() {
      const routeName = this.$route.name;
      if (routeName === 'home') return 'fade';
      if (routeName === 'about') return 'slide';
      return 'default';
    }
  }
};
</script>

<template>
  <transition :name="transitionName" mode="out-in">
    <router-view />
  </transition>
</template>

JavaScript-хуки анимаций

Vue Router позволяет использовать хуки перехода для более точного контроля. <transition> поддерживает следующие события:

  • before-enter(el)
  • enter(el, done)
  • after-enter(el)
  • before-leave(el)
  • leave(el, done)
  • after-leave(el)

Пример использования:

<transition
  @before-enter="beforeEnter"
  @enter="enter"
  @leave="leave"
>
  <router-view />
</transition>

<script>
export default {
  methods: {
    beforeEnter(el) {
      el.style.opacity = 0;
    },
    enter(el, done) {
      gsap.to(el, { opacity: 1, duration: 0.5, onComplete: done });
    },
    leave(el, done) {
      gsap.to(el, { opacity: 0, duration: 0.5, onComplete: done });
    }
  }
};
</script>

Анимация при вложенных маршрутах

При работе с вложенными маршрутами <router-view> может быть вложен в другие компоненты. Чтобы анимация работала корректно, важно оборачивать каждый <router-view> в отдельный <transition> или управлять их через динамические имена переходов.

<transition :name="parentTransition" mode="out-in">
  <router-view />
</transition>

<!-- Внутри дочерней компоненты -->
<transition :name="childTransition" mode="out-in">
  <router-view />
</transition>

Использование <keep-alive> и анимации

Если необходимо сохранять состояние компонента между переходами, <keep-alive> можно комбинировать с <transition>:

<transition name="fade" mode="out-in">
  <keep-alive>
    <router-view v-if="$route.meta.keepAlive" />
  </keep-alive>
  <router-view v-else />
</transition>

Такой подход позволяет сохранять состояние компонентов и одновременно применять анимации входа и выхода.

Сложные переходы с динамическими маршрутами

Для SPA с изменяющимся контентом на одной странице (например, с параметрами маршрута) удобно использовать watch на $route и изменять состояние анимации через классы или динамические свойства.

watch: {
  $route(to, from) {
    this.transitionName = to.params.id > from.params.id ? 'slide-left' : 'slide-right';
  }
}

Рекомендации по производительности

  • Минимизировать использование сложных анимаций на больших компонентах
  • Стараться применять GPU-friendly свойства (transform, opacity)
  • Для анимаций с длительной нагрузкой использовать JavaScript-хуки для управления жизненным циклом

Эти подходы обеспечивают плавные и отзывчивые переходы между маршрутами, улучшая пользовательский опыт в приложениях на Vue.js с Vue Router.