CSS переходы в Vue

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

<template>
  <transition name="fade">
    <p v-if="show">Пример текста с переходом</p>
  </transition>
</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>

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

  • v-if управляет наличием элемента в DOM, инициируя переход.
  • Классы *-enter-* и *-leave-* применяются автоматически.
  • *-active определяет длительность и свойства анимации через transition.

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

Vue разделяет процесс анимации на четыре класса:

  1. v-enter-from — начальное состояние элемента при появлении.
  2. v-enter-to — конечное состояние элемента при завершении анимации появления.
  3. v-leave-from — начальное состояние элемента при исчезновении.
  4. v-leave-to — конечное состояние элемента при завершении анимации исчезновения.

Пример с масштабированием:

<template>
  <transition name="scale">
    <div v-if="visible" class="box"></div>
  </transition>
</template>

<script>
export default {
  data() {
    return {
      visible: false
    }
  }
}
</script>

<style>
.scale-enter-active, .scale-leave-active {
  transition: transform 0.3s ease;
}
.scale-enter-from, .scale-leave-to {
  transform: scale(0);
}
.scale-enter-to, .scale-leave-from {
  transform: scale(1);
}
.box {
  width: 100px;
  height: 100px;
  background-color: #42b983;
}
</style>

Пользовательские классы и атрибуты

Атрибут name компонента <transition> автоматически добавляет префикс к классам. Для более гибкого контроля доступны следующие атрибуты:

  • appear — включает анимацию при первоначальном рендере элемента.
  • mode — определяет последовательность анимации для нескольких элементов (in-out, out-in).
<transition name="fade" appear mode="out-in">
  <p v-if="show">Текст с появлением и уходом</p>
</transition>

Режимы анимации:

  • in-out: новый элемент сначала появляется, затем старый исчезает.
  • out-in: старый элемент исчезает полностью, после чего появляется новый.

Анимации нескольких элементов

Для анимации списков используется <transition-group>. Он добавляет анимацию при добавлении, удалении и перемещении элементов.

<template>
  <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: 'Элемент 1' },
        { id: 2, text: 'Элемент 2' }
      ]
    }
  }
}
</script>

<style>
.list-enter-active, .list-leave-active {
  transition: all 0.4s ease;
}
.list-enter-from, .list-leave-to {
  opacity: 0;
  transform: translateY(20px);
}
.list-enter-to, .list-leave-from {
  opacity: 1;
  transform: translateY(0);
}
</style>

Особенности:

  • tag позволяет указать контейнер для группы элементов.
  • Каждый элемент списка должен иметь уникальный key для корректного отслеживания.

JavaScript-хуки переходов

Помимо CSS, Vue позволяет управлять переходами через JavaScript-хуки: before-enter, enter, after-enter, before-leave, leave, after-leave. Они дают полный контроль над анимацией и интеграцию с библиотеками типа GSAP или anime.js.

<transition
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:after-enter="afterEnter">
  <div v-if="show" class="box"></div>
</transition>

<script>
export default {
  methods: {
    beforeEnter(el) {
      el.style.opacity = 0;
    },
    enter(el, done) {
      gsap.to(el, { opacity: 1, duration: 0.5, onComplete: done });
    },
    afterEnter(el) {
      console.log('Анимация завершена');
    }
  }
}
</script>

Преимущества использования хуков:

  • Позволяют комбинировать CSS и JS-анимации.
  • Даётся контроль над сложными последовательностями.
  • Поддерживают асинхронные операции.

Комбинированные подходы

Часто используется сочетание CSS и JS-переходов. CSS управляет простыми анимациями (например, fade, scale), а JS-хуки выполняют более сложные эффекты или синхронизацию с внешними библиотеками.

<transition
  name="fade-scale"
  v-on:enter="animateEnter"
  v-on:leave="animateLeave">
  <div v-if="active" class="box"></div>
</transition>

<script>
export default {
  methods: {
    animateEnter(el, done) {
      el.style.transform = 'scale(0)';
      gsap.to(el, { scale: 1, opacity: 1, duration: 0.4, onComplete: done });
    },
    animateLeave(el, done) {
      gsap.to(el, { scale: 0, opacity: 0, duration: 0.4, onComplete: done });
    }
  }
}
</script>

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

Такой подход обеспечивает плавность визуальных эффектов, сохраняя управляемость через Vue и расширяемость с использованием JavaScript.


Советы по производительности

  • Ограничивать количество одновременно анимируемых элементов.
  • Использовать transform и opacity, так как они GPU-ускоренные.
  • Минимизировать изменения layout (width, height, margin), чтобы избежать reflow.
  • Для списков применять key, чтобы Vue правильно отслеживал элементы и использовал переходы эффективно.