Представьте, что ваш проект на Vue.js превратился в огромный склад, где вещи лежат по категориям: здесь все данные, там - методы, а в другом конце здания - хуки жизненного цикла. Когда компонент маленький, это удобно. Но когда в нем сотни строк кода, вам приходится постоянно бегать между разделами, чтобы понять, как одна переменная влияет на конкретный метод. Именно эту проблему решает переход на Composition API, новый подход к разработке компонентов в Vue 3, который позволяет группировать логику по функциональным признакам, а не по типу опций.
Если вы до сих пор используете Options API, вы не обязаны переписывать всё приложение за одну ночь. Vue 3 спроектирован так, чтобы оба подхода могли сосуществовать. Однако переход на новый стандарт дает реальные преимущества в поддержке кода и типизации. Давайте разберем, как переехать с одного API на другое, не сломав при этом работающий бизнес.
Краткий гид по замене опций
Главная задача при миграции - правильно сопоставить старые разделы компонента с новыми функциями. В Options API логика была жестко распределена по объектам, а в Composition API мы используем импортируемые функции из ядра Vue.
| Options API (Vue 2/3) | Composition API (Vue 3) | Что изменилось? |
|---|---|---|
| data() | ref(), reactive() | Состояние теперь создается через функции реактивности |
| computed: { ... } | computed(() => ...) | Вычисляемые свойства стали функциями |
| methods: { ... } | Обычные JS-функции | Методы больше не живут в отдельном объекте |
| mounted(), created() | onMounted(), onCreated() | Хуки теперь импортируются и вызываются внутри setup |
| watch: { ... } | watch(), watchEffect() | Наблюдатели стали более гибкими функциями |
Магия <script setup>: почему это стандарт
Если вы только начинаете переезд, забудьте про классическую функцию setup() и переходите сразу к синтаксису <script setup>. Это «сахар», который делает код намного чище. Раньше вам приходилось возвращать все переменные и методы в конце функции setup, чтобы они были доступны в шаблоне. Теперь всё, что объявлено в блоке <script setup>, автоматически попадает в шаблон.
Для работы с пропсами и событиями здесь используются специальные макросы, которые не нужно импортировать:
defineProps()- заменяет опциюprops. Позволяет четко определить типы данных, которые принимает компонент.defineEmits()- заменяетemits. Теперь вы явно объявляете, какие события компонент может отправить наверх.defineOptions()- появился в Vue 3.3, позволяет задавать имя компонента или настраиватьinheritAttrsпрямо внутри setup-блока.
Такой подход не только сокращает количество шаблонного кода, но и заметно уменьшает размер итогового бандла, так как компилятор может оптимизировать такие компоненты более эффективно.
Практический пример миграции
Допустим, у нас есть компонент счетчика воды. В Options API он выглядел бы так: мы создали cupsOfWater в data, метод drinkCup в methods и следили за изменением через watch. Всю эту логику приходится «размазывать» по всему файлу.
При переезде на Composition API мы создаем ref для счетчика, обычную функцию для логики «питье воды» и вызываем watch прямо рядом с переменной, за которой следим. В итоге вся логика управления водой сосредоточена в одном блоке кода. Если вам понадобится перенести этот функционал в другой компонент, вы просто выносите его в отдельный файл - так называемый composable (композабл). Это и есть главная киллер-фича: переиспользование логики без сложных миксинов, которые в Vue 2 часто приводили к конфликтам имен.
Интеграция с TypeScript: конец эпомтев и ошибок
Одна из главных причин, почему крупные enterprise-проекты переходят на Composition API, - это TypeScript. В Options API типизация была довольно костыльной: вам приходилось описывать типы через сложные интерфейсы или использовать Vue.extend. TypeScript плохо «понимал», что именно возвращает this внутри метода.
В Composition API всё работает на обычных функциях и переменных. Типизация здесь естественна. Если вы создаете ref<number>(0), IDE сразу подскажет вам, что здесь может быть только число. Это сокращает количество багов на этапе разработки и делает автодополнение в VS Code действительно полезным.
Стратегия «мягкого» переезда
Не пытайтесь переписать всё приложение за один спринт. Это прямой путь к бесконечным регрессионным тестам и выгоранию команды. Лучше всего использовать инкрементальный подход:
- Новые компоненты - только на Composition API. Это позволит команде привыкнуть к новому синтаксису без риска сломать старый функционал.
- Миграция при рефакторинге. Переписывайте старый компонент на Composition API только тогда, когда вам всё равно нужно в него залезть для добавления фичи или исправления бага.
- Использование @vue/compat. Если вы переходите с Vue 2 на Vue 3, установите миграционный билд. Он будет выдавать предупреждения в консоли о том, какие части вашего кода больше не поддерживаются и как их исправить.
Помните, что Options API никуда не исчезнет в ближайшее время. Он всё еще поддерживается и работает в Vue 3. Но если вы хотите строить масштабируемую архитектуру, Composition API - единственный путь.
Опасные моменты и подводные камни
Переход не обходится без ошибок. Самая частая проблема новичков - путаница между ref() и reactive(). Если вы используете ref, не забывайте, что в JavaScript-коде доступ к значению идет через .value (например, count.value++), хотя в шаблоне Vue делает это автоматически. reactive() удобен для объектов, но он «теряет» реактивность, если вы попытаетесь деструктурировать его или заменить весь объект целиком.
Также будьте осторожны при миграции с vue-class-component. Классовый подход был популярен в эпоху Vue 2, но в Vue 3 он считается антипаттерном. Переход с классов на функции может потребовать пересмотра всей структуры компонентов.
Нужно ли переписывать все компоненты на Composition API для работы Vue 3?
Нет, не обязательно. Options API полностью поддерживается в Vue 3. Вы можете использовать оба подхода в одном проекте или даже в одном компоненте (через функцию setup). Переписывайте код только тогда, когда это приносит реальную пользу в виде упрощения поддержки или улучшения типизации.
Что лучше: ref или reactive?
Для простых значений (строки, числа, булевы значения) используйте ref(). Для сложных объектов и массивов можно использовать reactive(), но многие разработчики предпочитают ref() даже для объектов, так как он более предсказуем и позволяет легко отслеживать изменения через .value, не теряя реактивность при переприсваивании.
Как заменить миксины (Mixins) в Composition API?
Вместо миксинов теперь используются composables - обычные функции, которые принимают параметры и возвращают реактивные состояния или методы. Это решает проблему «невидимых» источников данных, которая была в миксинах, так как теперь вы явно импортируете и вызываете нужную функцию.
Будет ли приложение работать быстрее после миграции?
Само по себе изменение API не дает колоссального прироста скорости выполнения, но использование <script setup> и удаление лишнего кода Options API (через флаги компилятора) может немного уменьшить размер итогового JS-бандла, что ускорит загрузку страницы.
Можно ли использовать Composition API в Vue 2?
Да, это возможно. В версии Vue 2.7 поддержка Composition API встроена в ядро. Для более старых версий Vue 2 можно использовать плагин @vue/composition-api, который позволяет начать переезд на новый синтаксис еще до обновления самого фреймворка.