Skip to content

Composition API FAQ

Совет

Данный FAQ предполагает наличие опыта работы с Vue - в частности, опыта работы с Vue 2 при преимущественном использовании API Options.

Что такое Composition API?

Composition API - это набор API, который позволяет нам создавать компоненты Vue, используя импортированные функции вместо объявления опций. Это обобщающий термин, который охватывает следующие API:

  • Reactivity API, например ref() и reactive(), что позволяет нам напрямую создавать реактивное состояние, вычисляемое состояние, и наблюдатели.

  • Хуки жизненного цикла, например onMounted() и onUnmounted(), которые позволяют нам программно подключаться к жизненному циклу компонента.

  • Инъекция зависимостей, то есть provide() и inject(), которые позволяют нам использовать систему dependency injection при использовании Reactivity API.

Composition API встроено во Vue 3 и Vue 2.7. Для более старых версий Vue 2 используйте официально поддерживаемый плагин @vue/composition-api. Во Vue 3, он также в основном используется вместе с <script setup> синтаксисом в однофайловых компонентах. Вот базовый пример компонента, использующего Composition API:

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

// реактивное состояние
const count = ref(0)

// функции, которые изменяют состояние и запускают обновления
function increment() {
  count.value++
}

// хуки жизненного цикла
onMounted(() => {
  console.log(`The initial count is ${count.value}.`)
})
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

Несмотря на стиль API, основанный на композиции функций, Composition API НЕ ЯВЛЯЕТСЯ функциональным программированием. Composition API основан на изменчивой, детализированной парадигме реактивности Vue, тогда как функциональное программирование делает упор на неизменность.

Если вам интересно узнать, как использовать Vue с Composition API, вы можете установить для всего сайта предпочитаемое API в Composition API, используя переключатель расположенный в верхней части боковой панели сайта с левой стороны, а затем пройти руководство с самого начала.

Почему Composition API?

Лучшее переиспользование логики

Основное преимущество Composition API заключается в том, что он обеспечивает чистое, эффективное повторное использование логики в виде Composable функций. Он решает все недостатки миксинов, основного механизма повторного использования логики в Options API.

Возможность повторного использования логики Composition API привела к созданию впечатляющих проектов сообщества, таких как VueUse, постоянно растущей коллекции композаблов. Он также служит чистым механизмом для простой интеграции сторонних служб или библиотек с отслеживанием состояния в систему реактивности Vue, например immutable data, state machines, и RxJS.

Более гибкая организация кода

Многим пользователям нравится, что мы по умолчанию пишем упорядоченный код с использованием Options API: все находится на своем месте в зависимости от того, к какой опции оно относится. Однако, Options API накладывает серьезные ограничения, когда логика одного компонента перерастает определенный порог сложности. Особенно ярко это ограничение проявляется в компонентах, где необходимо решать несколько логических задач, что мы наглядно можем наблюдать во многих рабочих приложениях Vue 2.

Возьмем для примера компонент проводника папок из графического интерфейса Vue CLI этот компонент отвечает за следующие логические задачи:

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

Первоначальная версия компонента была написана на Options API. Если мы присвоим каждой строке кода цвет в зависимости от того, с какой логической задачей она связана, это будет выглядеть так:

компонент папки до

Обратите внимание, как код, связанный с одной и той же логической задачей, вынужден разделяться по разным параметрам, расположенным в разных частях файла. В компоненте длиной в несколько сотен строк понимание и навигация по одной логической задаче требует постоянной прокрутки вверх и вниз по файлу, что значительно усложняет задачу. Кроме того, если мы когда-нибудь собираемся извлечь логическую проблему в повторно используемую утилиту, потребуется немало усилий, чтобы найти и извлечь нужные фрагменты кода из разных частей файла.

Вот тот же компонент, до и после реорганизации с использованием Composition API:

компонент папки после

Обратите внимание, как код, относящийся к одной логической задаче, теперь можно сгруппировать вместе: нам больше не нужно переходить между разными блоками параметров при работе с определенной логической задачей. Более того, теперь мы можем перемещать группу кода во внешний файл с минимальными усилиями, так как нам больше не нужно перетасовывать код, чтобы извлечь его. Это снижение сложности рефакторинга является ключом к долгосрочной поддержке больших кодовых баз.

Лучшее выведение типов

В последние годы все больше и больше разработчиков интерфейсов переходят на TypeScript поскольку это помогает нам писать более надежный код, вносить изменения с большей уверенностью и обеспечивает отличный опыт разработки с поддержкой IDE. Однако Options API, изначально задуманный в 2013 году, был разработан без учета вывода типов. Нам пришлось реализовать некоторые абсурдно сложные гимнастические упражнения с типами, чтобы вывод типов работал с Options API. Даже при всех этих усилиях вывод типов для Options API может по-прежнему не работать для mixins и dependency injection.

Это привело к тому, что многие разработчики, которые хотели использовать Vue с TS, склонялись к Class API основанному на vue-class-component. Однако API на основе классов в значительной степени зависит от декораторов ES, языковой функции, которая была предложена только на этапе 2, когда Vue 3 разрабатывался в 2019 году. Мы посчитали слишком рискованным основывать официальный API на нестабильном предложении. С тех пор предложение декораторов претерпело еще одну полную переработку, и наконец, достигло 3 этапа в 2022 году. Кроме того, API на основе классов страдает от повторного использования логики и организационных ограничений, подобных Options API.

Для сравнения, Composition API использует в основном простые переменные и функции, которые, естественно, дружественны к типам. Код, написанный в Composition API может использовать полный вывод типов с небольшой потребностью в ручных подсказках. Большую часть времени, код Composition API будет выглядеть практически одинаково в TypeScript и простом JavaScript. Это также позволяет обычным пользователям JavaScript извлекать выгоду из частичного вывода типов.

Меньший размер production сборки и меньше накладных расходов

Код, написанный в Composition API и <script setup> также более эффективен и удобен для минификации, чем аналогичный в Options API. Это связано с тем, что шаблон в компоненте <script setup> скомпилирован как функция, встроенная в ту же область действия кода <script setup>. В отличие от доступа к свойствам через this, скомпилированный код шаблона может напрямую обращаться к переменным, объявленным внутри <script setup>, без промежуточного прокси экземпляра. Это также приводит к лучшей минимизации, поскольку все имена переменных можно безопасно сократить.

Связь с Options API

Компромиссы

Некоторые пользователи, перешедшие с Options API, обнаружили, что их код Composition API менее организован, и пришли к выводу, что Composition API «хуже» с точки зрения организации кода. Мы рекомендуем пользователям с таким мнением посмотреть на эту проблему с другой точки зрения.

Это правда, что Composition API больше не предоставляет «ограничителей», которые помогут вам поместить свой код в соответствующие корзины. В свою очередь, вы получаете возможность создавать код компонента, как если бы вы писали обычный JavaScript. Это означает, что вы можете и должны применять любые передовые методы организации кода к своему коду Composition API как при написании обычного JavaScript. Если вы можете написать хорошо организованный JavaScript, вы также сможете написать хорошо организованный код Composition API.

Options API позволяет вам «меньше думать» при написании кода компонентов, поэтому многим пользователям это нравится. Однако, уменьшая умственные затраты, он также привязывает вас к предписанному шаблону организации кода без возможности выхода, что может затруднить рефакторинг или улучшение качества кода в крупномасштабных проектах. В этом отношении Composition API обеспечивает лучшую долгосрочную масштабируемость.

Охватывает ли Composition API все варианты использования?

Да, с точки зрения логики состояния. При использовании Composition API может понадобиться всего несколько параметров: props, emits, name и inheritAttrs. Если используется <script setup>, то inheritAttrs обычно является единственным параметром, для которого может потребоваться отдельный обычный <script> блок.

Совет

С версии 3.3 вы можете напрямую использовать defineOptions в <script setup> чтобы установить имя компонента или свойство inheritAttrs

Если вы намерены использовать исключительно Composition API (наряду с перечисленными выше параметрами), вы можете уменьшить сборку для production на несколько килобайт с помощь compile-time flag который удаляет код, связанный с Options API, из Vue. Обратите внимание, что это также влияет на компоненты Vue в ваших зависимостях.

Могу ли я использовать совместно оба API?

Да. Вы можете использовать Composition API через setup() в компоненте Options API.

Однако мы рекомендуем делать это только в том случае, если у вас есть существующая кодовая база Options API, которую необходимо интегрировать с новыми функциями/внешними библиотеками, написанными с помощью Composition API.

Будет ли Options API объявлен устаревшим?

Нет, у нас нет никаких планов по этому поводу. Options API неотъемлемая часть Vue, и именно поэтому он нравится многим разработчикам. Мы также понимаем, что многие преимущества Composition API проявляются только в крупномасштабных проектах, и Options API остается хорошим выбором для многих сценариев низкой и средней сложности.

Связь с Class API

Мы больше не рекомендуем использовать Class API с Vue 3, учитывая, что Composition API обеспечивает отличную интеграцию TypeScript с дополнительными преимуществами повторного использования логики и организации кода.

Сравнение с React Hooks

Composition API обеспечивает тот же уровень возможностей логической композиции, что и React Hooks, но с некоторыми важными отличиями.

React Hooks повторно вызываются каждый раз при обновлении компонента. Это создает ряд предостережений, которые могут сбить с толку даже опытных разработчиков React. Это также приводит к проблемам с оптимизацией производительности, которые могут серьезно повлиять на процесс разработки. Вот некоторые примеры:

  • Hooks чувствительны к порядку вызова и не могут быть условными.

  • Переменные, объявленные в компоненте React, могут быть захвачены замыканием хука и стать «устаревшими», если разработчику не удастся передать правильный массив зависимостей. Это приводит к тому, что разработчики React полагаются на правила ESLint для обеспечения передачи правильных зависимостей. Однако правило часто недостаточно умно и чрезмерно компенсирует правильность, что приводит к ненужной инвалидации и головной боли при возникновении крайних случаев.

  • Дорогие вычисления требуют использования useMemo, что опять же требует ручной передачи правильного массива зависимостей.

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

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

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

Для сравнения, Vue Composition API:

  • Вызывает код setup() или <script setup> только один раз. Это делает код более соответствующим интуитивному использованию идиоматического JavaScript, поскольку не нужно беспокоиться об устаревших замыканиях. Вызовы Composition API также не зависят от порядка вызовов и могут быть условными.

  • Система реактивности среды выполнения Vue автоматически собирает реактивные зависимости, используемые в вычисляемых свойствах и наблюдателях, поэтому нет необходимости вручную объявлять зависимости.

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

Мы признаем креативность React Hooks, и это главный источник вдохновения для Composition API. Тем не менее, проблемы, упомянутые выше, действительно существуют в его дизайне, и мы заметили, что модель реактивности Vue позволяет их обойти.

Composition API FAQУже загружено