Хуки переходов

Vue.js предоставляет мощный механизм для работы с анимациями и переходами компонентов и элементов DOM. Основой управления переходами являются хуки жизненного цикла анимаций, которые позволяют выполнять произвольный код в ключевые моменты анимационного процесса.

Основные хуки переходов

Vue поддерживает несколько встроенных хуков для работы с переходами, каждый из которых отвечает за определённый этап анимации:

  • before-enter — вызывается до начала добавления элемента в DOM и перед запуском анимации. На этом этапе можно подготовить элемент: задать начальные стили, вычислить размеры или скрыть элемент.

  • enter — запускается сразу после добавления элемента в DOM. Этот хук используется для применения анимационных классов или запуска JavaScript-анимаций.

  • after-enter — срабатывает после завершения анимации появления. На этом этапе обычно выполняются завершающие действия, например, снятие временных стилей или уведомление других частей приложения о завершении анимации.

  • enter-cancelled — вызывается, если анимация появления была прервана до завершения. Позволяет корректно откатить изменения и вернуть элемент в исходное состояние.

  • before-leave — вызывается перед началом анимации удаления элемента из DOM. Используется для подготовки элемента к уходящей анимации: добавления стилей, вычисления размеров и т.п.

  • leave — запускает сам процесс анимации ухода элемента. Здесь можно добавлять классы или использовать JavaScript-анимации с контролем длительности и прогресса.

  • after-leave — срабатывает после завершения ухода элемента. Обычно выполняется очистка временных стилей и удаление ссылок на элемент, если требуется.

  • leave-cancelled — аналогично enter-cancelled, срабатывает при прерывании анимации ухода, что позволяет вернуть элемент в корректное состояние.

Использование хуков в шаблоне

Vue позволяет привязывать хуки к элементам через компонент <transition>:

<template>
  <transition
    @before-enter="beforeEnter"
    @enter="enter"
    @after-enter="afterEnter"
    @before-leave="beforeLeave"
    @leave="leave"
    @after-leave="afterLeave"
  >
    <div v-if="isVisible" class="box">Контент</div>
  </transition>
</template>

<script>
export default {
  data() {
    return {
      isVisible: false
    };
  },
  methods: {
    beforeEnter(el) {
      el.style.opacity = 0;
      el.style.transform = 'translateY(-20px)';
    },
    enter(el, done) {
      const animation = el.animate([
        { opacity: 0, transform: 'translateY(-20px)' },
        { opacity: 1, transform: 'translateY(0)' }
      ], { duration: 300 });
      animation.onfin ish = done;
    },
    afterEnter(el) {
      el.style.opacity = '';
      el.style.transform = '';
    },
    beforeLeave(el) {
      el.style.opacity = 1;
      el.style.transform = 'translateY(0)';
    },
    leave(el, done) {
      const animation = el.animate([
        { opacity: 1, transform: 'translateY(0)' },
        { opacity: 0, transform: 'translateY(-20px)' }
      ], { duration: 300 });
      animation.onfin ish = done;
    },
    afterLeave(el) {
      el.style.opacity = '';
      el.style.transform = '';
    }
  }
};
</script>

<style>
.box {
  width: 200px;
  height: 100px;
  background-color: #42b983;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>

В этом примере каждый хук выполняет конкретную задачу, от подготовки элемента до управления анимацией и очистки после её завершения. Использование колбэка done важно для асинхронных анимаций, чтобы Vue корректно отслеживал завершение перехода.

Разница между CSS-переходами и JavaScript-хуками

Vue автоматически добавляет классы для CSS-анимаций (v-enter, v-enter-active, v-leave-active и т. д.), что позволяет описывать переходы чисто через CSS. Хуки JavaScript применяются тогда, когда требуется динамическое управление анимацией, вычисление промежуточных состояний или использование сложных библиотек для анимации.

Преимущества JavaScript-хуков:

  • Полный контроль над начальным и конечным состоянием элементов.
  • Возможность работы с элементами, размеры которых вычисляются динамически.
  • Интеграция с внешними библиотеками анимаций (GSAP, Velocity.js).

Недостатки:

  • Немного сложнее в реализации.
  • Может потребоваться ручное управление завершением анимации через done.

События хуков для компонентов

Хуки переходов применимы не только к DOM-элементам, но и к компонентам. Для компонентов <transition> автоматически передаёт хуки дочернему компоненту через слоты и пропсы. Это позволяет управлять анимацией внутри сложной структуры компонентов без необходимости вмешательства в внутреннюю логику каждого компонента.

Практические советы

  • Для плавных эффектов лучше комбинировать CSS и JavaScript-хуки: CSS для базовой анимации, JS для динамических изменений.
  • Всегда использовать done для асинхронных переходов, чтобы предотвратить рассинхронизацию состояний.
  • Проверять возможность прерывания анимации и корректно обрабатывать хуки enter-cancelled и leave-cancelled.
  • Для сложных анимаций с множеством элементов использовать директиву v-for вместе с <transition-group> и соответствующими хуками.

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