Vue 3 Composition API: От Options к Композиции с Практическими Примерами

Vue 3 Composition API: От Options к Композиции с Практическими Примерами

Если вы работали с Vue 2, то привыкли к Options API — чёткому, но иногда громоздкому разделению логики по опциям data, methods, computed. Vue 3 представил Composition API — революционный подход, который позволяет организовывать код по функциональности, а не по типам опций. Это не просто новый синтаксис, а философия написания более гибких, переиспользуемых и поддерживаемых компонентов. В этой статье мы погрузимся в суть Composition API и разберём практические примеры, которые покажут его мощь.

Что такое Composition API и зачем он нужен?

Composition API — это набор функций, в первую очередь ref, reactive, computed, watch и onMounted, которые можно вызывать внутри функции setup() или в теге <script setup>. Основная цель — логическая композиция: связанная функциональность собирается вместе, а не размазывается по разным секциям компонента.

Ключевое преимущество: Composition API идеально подходит для выделения переиспользуемой логики в композаблы (composables) — самостоятельные функции, которые можно «подключать» к разным компонентам, как конструктор.

Базовый пример: от Options к Composition

Рассмотрим простой счётчик на Options API:

// Options API (Vue 2 стиль)
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count++
    }
  }
}

Тот же компонент на Composition API с использованием <script setup> (самый современный синтаксис):

<script setup>
import { ref } from 'vue'

const count = ref(0)
const increment = () => {
  count.value++
}
</script>

Обратите внимание: реактивное состояние создаётся с помощью ref, а обращение к значению происходит через .value в JavaScript, но в шаблоне можно писать просто {{ count }}.

Практические примеры композаблов

Настоящая сила Composition API раскрывается при создании собственных композаблов.

Пример 1: Композабл для работы с мышью

// useMouse.js
import { ref, onMounted, onUnmounted } from 'vue'

export function useMouse() {
  const x = ref(0)
  const y = ref(0)

  const update = (event) => {
    x.value = event.pageX
    y.value = event.pageY
  }

  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  return { x, y }
}

Использование в компоненте:

<script setup>
import { useMouse } from './useMouse'
const { x, y } = useMouse()
</script>

<template>
  <p>Позиция мыши: {{ x }}, {{ y }}</p>
</template>

Пример 2: Композабл для загрузки данных

// useFetch.js
import { ref, onMounted } from 'vue'

export function useFetch(url) {
  const data = ref(null)
  const error = ref(null)
  const loading = ref(false)

  const fetchData = async () => {
    loading.value = true
    try {
      const response = await fetch(url)
      data.value = await response.json()
    } catch (e) {
      error.value = e
    } finally {
      loading.value = false
    }
  }

  onMounted(fetchData)

  return { data, error, loading, refetch: fetchData }
}

Композаблы инкапсулируют логику с её собственным жизненным циклом. Это делает код компонентов чище и позволяет легко тестировать логику отдельно от UI.

Работа с реактивностью: ref vs reactive

Vue 3 предлагает два основных способа создания реактивных объектов:

  • ref — для примитивов и объектов. Требует обращения через .value.
  • reactive — только для объектов. Не требует .value, но теряет реактивность при деструктуризации.
// Использование reactive
import { reactive, toRefs } from 'vue'

const state = reactive({
  name: 'Иван',
  age: 30
})

// Для деструктуризации с сохранением реактивности используем toRefs
const { name, age } = toRefs(state)

Жизненный цикл в Composition API

Хуки жизненного цикла становятся функциями, которые нужно явно импортировать и вызывать в setup:

import { onMounted, onUpdated, onUnmounted } from 'vue'

onMounted(() => {
  console.log('Компонент смонтирован')
})

onUpdated(() => {
  console.log('Компонент обновлён')
})

Когда использовать Composition API?

  1. Сложные компоненты с множеством пересекающихся функций.
  2. Переиспользование логики между несколькими компонентами.
  3. Типизация с TypeScript — Composition API обеспечивает превосходную поддержку типов.
  4. Работа в команде — логическая группировка облегчает понимание кода.

FAQ: Часто задаваемые вопросы

Composition API заменяет Options API?

Нет, это дополнительный, более гибкий подход. Options API остаётся полностью поддерживаемым и отлично подходит для простых компонентов.

Обязательно ли использовать <script setup>?

Нет, это синтаксический сахар. Можно использовать обычную функцию setup(), но <script setup> значительно сокращает boilerplate-код.

Сложно ли перейти с Vue 2 на Composition API?

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

Можно ли миксовать Composition и Options API?

Да, в компоненте можно использовать и setup() (Composition), и другие опции, такие как data или methods, но это усложняет понимание. Рекомендуется придерживаться одного стиля.