логотип PurpleSchool
логотип PurpleSchool

Использование transition во Vue

Автор

Олег Марков

Введение

Веб-приложения должны быть не только функциональными, но и отзывчивыми для пользователя. Анимации и плавные переходы делают интерфейсы более приятными и современными. В экосистеме Vue для этого предусмотрен специальный способ — компонент <transition>, который помогает вам создавать анимированное появление, исчезновение и изменение состояния DOM-элементов и компонентов.

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

Что такое transition во Vue и зачем он нужен

В библиотеке Vue создание анимированных изменений элементов достигается с помощью специального компонента <transition>. Его задача — облегчить добавление CSS анимаций или анимировать изменения на JavaScript при появлении, скрытии или переключении элементов.

Когда вы оборачиваете элемент или компонент в <transition>, Vue автоматически добавляет и удаляет определённые CSS-классы на нужных этапах жизненного цикла перехода. Благодаря этому вы можете прописывать стили для разных состояний — и получать плавное, предсказуемое поведение без лишней «магии».

Когда стоит использовать <transition>

  • При отображении элементов по условию (v-if, v-show)
  • При удалении элементов из DOM
  • Для анимации появления вложенных компонентов
  • Для простых fade-in/fade-out эффектов
  • Для комбинирования анимаций при смене содержимого

Как работает <transition> во Vue

Давайте разберёмся, как всё устроено.

Базовый пример: fade-in и fade-out

Рассмотрим простую задачу — нужно плавно показывать и скрывать элемент на странице:

<template>
  <div>
    <button @click="show = !show">
      Переключить блок
    </button>
    <transition name="fade">
      <p v-if="show">Этот текст появляется и исчезает плавно</p>
    </transition>
  </div>
</template>

<script>
export default {
  data() {
    return {
      show: true
    }
  }
}
</script>

<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.5s;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
.fade-enter-to, .fade-leave-from {
  opacity: 1;
}
</style>

Пояснения к коду

// Кнопка меняет флаг show, управляющий видимостью абзаца // Элемент <p> обернут в <transition name="fade"> // CSS-классы отвечают за разные состояния появления и скрытия

Под капотом

Когда флаг show переключается:

  • Vue добавляет класс .fade-enter-from в начале появления элемента и плавно переключает на .fade-enter-to.
  • При скрытии — добавляет .fade-leave-from и затем .fade-leave-to.
  • Класс .fade-enter-active и .fade-leave-active управляет самим переходом.

Классы состояния перехода во Vue

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

СостояниеДля v-enterДля v-leave
Началоv-enter-fromv-leave-from
Активный переходv-enter-activev-leave-active
Конецv-enter-tov-leave-to

Если вы используете атрибут name="fade", то префикс будет fade: fade-enter-from, fade-leave-to, и т.д.

Управление временем перехода

Вы можете использовать любые свойства CSS transition или animation. Например:

.slide-enter-active, .slide-leave-active {
  transition: all 0.4s cubic-bezier(.55,0,.1,1);
}
.slide-enter-from, .slide-leave-to {
  transform: translateY(-25px);
  opacity: 0;
}
.slide-enter-to, .slide-leave-from {
  transform: translateY(0);
  opacity: 1;
}

Теперь элемент будет не только плавно проявляться по прозрачности, но и «прилетать» сверху.

Применение к v-if и v-show

  • v-if: элемент добавляется и удаляется из DOM, transition работает при монтировании и размонтировании.
  • v-show: элемент остается в DOM и управляет только свойством display, но transition тоже можно подключить.

Пример для v-show: html <transition name="fade"> <div v-show="visible">Содержимое блока</div> </transition>

Vue обрабатывает анимацию идентично, но имейте в виду: v-show просто переключает display, а v-if действительно добавляет/удаляет элемент из DOM.

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

Иногда хочется, чтобы появление и исчезновение происходили с разными эффектами. Vue это поддерживает:

.bounce-enter-active {
  animation: bounce-in 0.6s;
}
.bounce-leave-active {
  animation: bounce-out 0.6s;
}
@keyframes bounce-in {
  0%   { transform: scale(0.5); opacity: 0;}
  100% { transform: scale(1); opacity: 1;}
}
@keyframes bounce-out {
  0%   { transform: scale(1); opacity: 1;}
  100% { transform: scale(1.2); opacity: 0;}
}

Эффект появления и исчезновения будут разными, при этом компонент остался тем же.

Пользовательские имена и множественные transition

Вы не ограничены одним вариантом. Можно использовать несколько transition с разными эффектами, просто указывайте соответствующий name.

Также можно динамически менять name: html <transition :name="show ? 'fade' : 'slide'"> <div v-if="isVisible">Контент</div> </transition>

Переходы при смене компонентов с помощью <transition>

Когда вы используете динамические компоненты (<component :is="...">), их также можно анимировать:

<transition name="fade" mode="out-in">
  <component :is="currentComponent"></component>
</transition>

mode="out-in" гарантирует, что исходный компонент полностью исчезнет, прежде чем появится новый.

События жизненного цикла transition

Vue позволяет реагировать на этапы transition через события (только для JavaScript-анимаций или дополнительных эффектов):

  • before-enter
  • enter
  • after-enter
  • enter-cancelled
  • before-leave
  • leave
  • after-leave
  • leave-cancelled

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

<transition
  @before-enter="beforeEnter"
  @enter="onEnter"
  @after-leave="cleanup"
>
  <div v-if="show">Анимируемый блок</div>
</transition>
methods: {
  beforeEnter(el) {
    // Можно задать начальные стили программы
    el.style.opacity = 0
  },
  onEnter(el, done) {
    // Можно использовать сторонние анимационные библиотеки
    $(el).animate({ opacity: 1 }, 500, done)
  },
  cleanup(el) {
    // Что-то убрать, когда анимация закончится
  }
}

Эти методы получают доступ к DOM-элементу для ручного управления, если CSS-анимаций недостаточно.

Безопасная анимация списков через <transition-group>

Для анимации добавления, удаления и сортировки элементов в списках используйте <transition-group>, который работает с массивами и выводит набор элементов с анимацией:

<template>
  <button @click="addItem">Добавить</button>
  <transition-group name="list" tag="ul">
    <li v-for="item in items" :key="item.id">
      {{ item.text }}
    </li>
  </transition-group>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, text: "Первый" },
        { id: 2, text: "Второй" }
      ]
    }
  },
  methods: {
    addItem() {
      this.items.push({ id: Date.now(), text: "Новый" })
    }
  }
}
</script>

<style>
.list-enter-active, .list-leave-active {
  transition: all 0.5s;
}
.list-enter-from {
  opacity: 0;
  transform: translateX(-30px);
}
.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}
</style>

Особенности

  • Используйте уникальный ключ (:key) для каждого элемента.
  • Можно задавать любой тег для контейнера через tag, например, ul, div или span.
  • Только тег, указанный в tag, будет группировать элементы.

Управление переходами с помощью JavaScript

Если возможностей CSS недостаточно (например, нужна интеграция с библиотеками анимации), можно полностью контролировать анимацию на JavaScript через методы событий переходит:

<transition
  @enter="customEnter"
  @leave="customLeave"
>
  <div v-if="visible">Кастомная анимация</div>
</transition>
methods: {
  customEnter(el, done) {
    // Запуск кастомной анимации появления
    someAnimationLib.show(el, done)
  },
  customLeave(el, done) {
    // Запуск кастомной анимации исчезновения
    someAnimationLib.hide(el, done)
  }
}

Главное помнить — вызывайте done() для завершения transition.

Особенности и подводные камни

Важность уникальных ключей

Для <transition-group> всегда указывайте явные и уникальные ключи. Без этого Vue не сможет корректно отслеживать порядок и анимировать перемещения элементов.

Используйте только один узел внутри <transition>

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

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

  • Не используйте transition на слишком больших списках или частых изменениях — это может замедлить рендеринг.
  • Используйте простые анимации (opacity, transform) — они аппаратно ускоряются и создают минимум нагрузки.

Совместное использование с animate.css и сторонними библиотеками

Вы легко можете комбинировать transition Vue и внешние библиотеки анимаций, просто добавив нужные классы в события жизненного цикла.

Заключение

Компонент <transition> — это мощный и в то же время простой инструмент для создания плавных анимаций интерфейса на Vue. Он отлично подходит как для простых fade-эффектов, так и для сложных переходов между состояниями компонентов и списков. Используя чётко определённые CSS-классы и события жизненного цикла, вы можете с легкостью кастомизировать поведение анимаций, повысив интерактивность ваших приложений без избыточного кода. Благодаря поддержке работы как с отдельными элементами, так и с группами, transition во Vue остаётся универсальным решением для всех популярных UI-задач.

Частозадаваемые технические вопросы по теме статьи

Как указать индивидуальную продолжительность для входа и выхода анимации?

Добавьте дополнительный атрибут :duration="{ enter: 500, leave: 800 }" в компонент <transition>. Это позволит явно задавать время появления и исчезновения в миллисекундах: html <transition name="fade" :duration="{ enter: 300, leave: 700 }"> <div v-if="visible"></div> </transition>

Как анимировать переход между элементами (например, между изображениями)?

Используйте <transition> с атрибутом mode="out-in". Это приведёт к тому, что сначала исчезнет текущий элемент, а затем появится новый: html <transition name="fade" mode="out-in"> <img :src="currentImage" :key="currentImage"> </transition> Убедитесь, что у элементов уникальные ключи.

Почему transition не работает с v-if, но работает с v-show?

v-if добавляет и удаляет элемент из DOM, если transition не применяется — проверьте структуру HTML (должен быть только один дочерний элемент), наличие необходимых CSS-классов и правильность их имени. Часто забывают задать правильный префикс name.

Как плавно анимировать изменение свойства (например размер блока), а не появление/исчезновение?

Используйте директиву <transition> вокруг блока с v-bind-стилями: html <transition name="resize"> <div :style="{ width: width + 'px' }" :key="width"></div> </transition> В CSS для класса .resize-enter-active, .resize-leave-active пропишите transition для изменения ширины.

Можно ли анимировать SVG элементы через transition?

Да, анимация возможна — просто поместите SVG-элемент внутрь <transition> и используйте CSS-анимацию для свойств SVG-элемента. Некоторые SVG свойства, такие как transform и opacity, анимируются корректно.

Тестирование компонентов и приложений на VueСтрелочка вправо

Все гайды по Vue

Работа с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueОбзор популярных шаблонов и стартовых проектов на VueКак организовать страницы и маршруты в проекте на VueСоздание серверных приложений на Vue с помощью Nuxt jsРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияНастройка и сборка проектов Vue с использованием современных инструментов
Управление переменными и реактивными свойствами во VueИспользование v for и slot в VueТипизация и использование TypeScript в VuejsИспользование шаблонов в Vue js для построения интерфейсовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsПонимание жизненного цикла компонента Vue js на примере mountedОсновы работы с объектами в VueИспользование метода map в Vue для обработки массивовОбработка пользовательского ввода в Vue.jsОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitИспользование директив и их особенности на Vue с помощью defineСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в Vue
Открыть базу знаний