Различные анимации для разных маршрутов

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


Компонент <transition> и его использование

Для анимации компонентов при смене маршрутов в Vue используется встроенный компонент <transition>:

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

<script>
export default {
  computed: {
    transitionName() {
      return this.$route.meta.transition || 'default';
    }
  }
}
</script>

<style>
.default-enter-active, .default-leave-active {
  transition: opacity 0.3s ease;
}
.default-enter-from, .default-leave-to {
  opacity: 0;
}
</style>

Ключевые моменты:

  • Атрибут :name задает базовое имя для CSS-классов анимации.
  • Атрибут mode="out-in" обеспечивает завершение анимации старого компонента перед появлением нового.
  • Использование meta-поля маршрута позволяет динамически выбирать анимацию для каждого маршрута.

Настройка анимаций через meta маршрутов

Vue Router позволяет добавлять произвольные данные к маршруту через объект meta. Это удобно для управления различными анимациями:

const routes = [
  { path: '/', component: Home, meta: { transition: 'fade' } },
  { path: '/about', component: About, meta: { transition: 'slide-left' } },
  { path: '/contact', component: Contact, meta: { transition: 'slide-right' } }
];

В этом примере каждому маршруту присвоена своя анимация:

  • fade — плавное исчезновение и появление.
  • slide-left — сдвиг компонента влево при входе.
  • slide-right — сдвиг компонента вправо при входе.

Определение CSS-анимаций

CSS-классы анимации формируются по шаблону:

<transition-name>-enter-active
<transition-name>-enter-from
<transition-name>-enter-to
<transition-name>-leave-active
<transition-name>-leave-from
<transition-name>-leave-to

Пример для анимации сдвига влево:

.slide-left-enter-active, .slide-left-leave-active {
  transition: transform 0.5s ease, opacity 0.5s ease;
}
.slide-left-enter-from {
  transform: translateX(100%);
  opacity: 0;
}
.slide-left-enter-to {
  transform: translateX(0);
  opacity: 1;
}
.slide-left-leave-from {
  transform: translateX(0);
  opacity: 1;
}
.slide-left-leave-to {
  transform: translateX(-100%);
  opacity: 0;
}

Аналогично можно задать сдвиг вправо или другие эффекты.


Динамическая смена анимаций через навигационные хуки

Для более сложных сценариев анимации можно использовать глобальные или локальные навигационные хуки:

router.beforeEach((to, from, next) => {
  const fromDepth = from.path.split('/').length;
  const toDepth = to.path.split('/').length;
  if (toDepth > fromDepth) {
    to.meta.transition = 'slide-left';
  } else {
    to.meta.transition = 'slide-right';
  }
  next();
});

Такой подход позволяет автоматически выбирать направление анимации в зависимости от “глубины” маршрута.


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

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

<transition :name="transitionName" mode="out-in">
  <keep-alive>
    <router-view v-if="$route.meta.keepAlive" />
  </keep-alive>
  <router-view v-else />
</transition>
  • Свойство keepAlive в meta позволяет контролировать, какие маршруты сохраняются в памяти.
  • Анимации работают корректно с включением и исключением <keep-alive> при переключении маршрутов.

Комбинирование нескольких анимаций

В сложных интерфейсах можно объединять эффекты:

.fade-slide-enter-active, .fade-slide-leave-active {
  transition: transform 0.5s ease, opacity 0.5s ease;
}
.fade-slide-enter-from {
  transform: translateY(20px);
  opacity: 0;
}
.fade-slide-enter-to {
  transform: translateY(0);
  opacity: 1;
}
.fade-slide-leave-from {
  transform: translateY(0);
  opacity: 1;
}
.fade-slide-leave-to {
  transform: translateY(-20px);
  opacity: 0;
}

Таким образом, компонент одновременно будет сдвигаться и плавно появляться/исчезать.


Управление анимациями с помощью JS-хуков

Для анимаций, которые нельзя выразить только CSS, можно использовать JS-хуки:

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

<script>
export default {
  methods: {
    beforeEnter(el) {
      el.style.opacity = 0;
    },
    enter(el, done) {
      Velocity(el, { opacity: 1, translateX: [0, 100] }, { duration: 500, complete: done });
    },
    leave(el, done) {
      Velocity(el, { opacity: 0, translateX: -100 }, { duration: 500, complete: done });
    }
  }
}
</script>
  • Использование библиотеки Velocity.js или аналогов позволяет создавать сложные анимации, контролируемые программно.
  • Методы beforeEnter, enter, leave дают полный контроль над стадиями анимации.

Выводы по организации анимаций

  • Присваивание анимаций через meta маршрутов обеспечивает чистую и гибкую структуру.
  • Использование <transition> с динамическим name позволяет легко менять эффекты.
  • Гибридный подход CSS + JS-хуки подходит для сложных сценариев и тонкой настройки поведения при переходах.
  • Навигационные хуки и keep-alive расширяют возможности управления анимациями на уровне маршрутизатора.

Разнообразие анимаций улучшает восприятие интерфейса, делая переходы логичными и визуально последовательными.