что такое composition api
Практическое введение в Composition API Vue 3
Composition API — это отличный способ делиться логикой приложения между компонентами в Vue.js. Вы сможете не только организовать повторяющиеся фрагменты кода в отдельные файлы, но и упростите их повторное использование.
Composition API позволяет сохранять реактивность переменных в общих фрагментах кода даже для приложений корпоративного размера, что может быть огромным достоинством по сравнению с реализациями в предыдущих версиях Vue. Согласно официальной документации, необходимость разработки Composition API обусловлена тем, что эффективное совместное использование кода разными компонентами вызывало проблемы в больших приложениях.
Хотя решения для выделения общих элементов, такие как миксин (mixin), компонент без рендеринга (renderless compontent) или HOC, существовали и прежде, ни одно из них не могло обеспечить столь высокую степень гибкости, как Composition API. Основным преимуществом этой новой функциональности является возможность одновременного извлечения элементов, которые прежде приходилось реализовывать для определенного компонента в данных, вычисляемых свойствах (computed) и методах (с помощью Options API). Рассмотрим краткий пример использования Composition API в реальных ситуациях.
В качестве первого шага создайте проект с помощью Vue.js (версия 3). Ради скорости я буду использовать для этой цели Vue Cli. По завершении проекта удалите компонент примера, он нам больше не понадобится. Уточните структуру проекта, в которую мы организуем код. Я помещаю свои компоненты в папку component под Src и одновременно создаю папку services, в которую упаковываю повторно используемый, но “бескомпонентный” код, реализующий бизнес-логику. Один файл содержит одну службу, например реализующую различные сортировки и фильтрации или http-вызовы.
Обычно мы не хотим описывать их как компоненты, их можно только правильно параметризовать, но мы хотим видеть данную логику в целом, как модуль в коде. Composition API как решение для реализации идеально вписывается в эту идею.
Composition API вводит новую часть в код компонента, называемую setup. Это функция, которая может иметь 2 параметра: контекст (context) и свойства (props). Внутри setup мы можем реализовать сегменты, которые написали в разделах данных, вычисляемых свойств (computed) и методов, используя известный ранее API Options. Здесь мы можем определить внутреннее состояние и функции компонента, а также здесь использовать общие фрагменты кода, которые я называю службами (services).
Во многих проектах мне нужны таблицы, которые можно отсортировать по столбцам в порядке возрастания или убывания. Мы создадим две таблицы, которые будут использовать одну и ту же службу направления. Это отличный реальный пример эффективности идеи Composition API.
Конечно, в корпоративном проекте нам пришлось бы передать всю табличную логику на аутсорсинг общему компоненту таблицы, который затем использует службу сортировки. Но мы не будем этого делать сейчас, потому что статья задумана для представления Composition API, которого будет достаточно для извлечения служебного кода из таблиц.
Компонент агрегации приложения HomePage отображает только две таблицы: в одной перечислены пользователи, а в другой — продукты. Composition API позволяет создавать операцию сортировки как отдельную службу, где при необходимости можно работать с реактивными значениями, которые затем можно сделать доступными в компонентах, использующих эту службу.
В этом примере я сохраню направление сортировки в собственной реактивной переменной службы. Я печатаю это значение порядка в обоих табличных компонентах в надписях на кнопках под данными. Я буду изменять порядок сортировки только и исключительно внутри службы сортировки четко видимым образом и когда это необходимо, компонент будет немедленно уведомлен об этом изменении, доказывая наличие реактивности.
Конечный результат
Компонент HomePage содержит две таблицы (и несколько строк кода css для выделения таблиц):
Компоненты ProductTable и UserTable
Компонент ProductTable показывает простую таблицу с 3 столбцами и кнопкой для сортировки внизу. Он определяет строки данных для простоты из строки 25.
Строка 35: выполняется сортировка с этой службой “во время загрузки” компонента (см. методы жизненного цикла vue 3).
Строка 8: это состояние может быть использовано в шаблоне непосредственно.
В службе сортировки нет ничего особенного, это просто очень простая функция. Она может сортировать заданный массив данных по свойству названия содержимого. Я не проверяю входные значения, потому что это не имеет значения с точки зрения примера Composition API. Важными сегментами являются реактивное состояние внутри службы (или функции) и возвращаемое значение в конце конструкции.
Помните: вы должны вернуть ВСЕ (функции, переменные и т. д.) из службы сортировки, чтобы сделать ее доступной на уровне компонента.
Интересные новинки Vue 3
Вместо предисловия
Vue используется во всех проектах FunCorp. Мы внимательно следим за развитием фреймворка, постоянно улучшаем процесс разработки и внедряем лучшие практики. И, конечно же, мы не могли пройти мимо и не перевести статью Филиппа Раковски, сооснователя VueStorefront, про новые фичи Vue 3, серьёзно влияющие на написание кода.
В прошлый раз мы рассматривали фичи, которые влияют на производительность Vue 3. Нам уже известно, что приложения, написанные на новой версии фреймворка, работают очень быстро, но производительность — не самое важное изменение. Для большинства разработчиков намного важнее то, как Vue 3 повлияет на стиль написания кода.
Как вы уже догадались, во Vue 3 появится много крутых фич. К счастью, команда Vue добавила больше улучшений и дополнений, чем ломающих изменений. Благодаря этому большинство разработчиков, знающих Vue 2, должны быстро освоиться в новом синтаксисе.
Давайте начнём с API, о котором многие из вас могли слышать.
Composition API
Composition API — самая обсуждаемая и упоминаемая фича следующей мажорной версии Vue. Синтаксис Composition API предоставляет абсолютно новый подход к организации и переиспользованию кода.
Сейчас мы создаём компоненты с синтаксисом, который называется Options API. Для того чтобы добавить логику, мы создаём свойства (опции) в объекте компонента, например data, methods, computed и т.д. Основным недостатком данного подхода является то, что это не JavaScript-код как таковой. Вам необходимо точно знать, какие опции доступны в шаблоне и каким будет поведение this. Компилятор Vue преобразует свойства в работающий JavaScript-код за вас. Из-за этой особенности мы не можем в полной мере пользоваться автодополнением или проверкой типов.
Composition API решает эту проблему и даёт возможность использовать механизмы, доступные через опции, с помощью обыкновенных JavaScript-функций.
Команда Vue описывает Composition API как «дополнительный, основанный на функциях API, позволяющий гибко использовать композицию в логике компонента». Код, написанный с помощью нового API, лучше читается, что делает его более лёгким для понимания.
Чтобы разобраться в том, как работает новый синтаксис, рассмотрим пример простого компонента.
Разобьём код на части и разберём, что же здесь происходит.
Как я уже упоминал выше, Composition API представляет опции компонента как функции, следовательно, первым делом мы должны импортировать необходимые функции. В этом примере нам нужно создать реактивное свойство с помощью ref, вычисляемое с помощью computed и получить доступ к хуку mounted жизненного цикла с помощью функции onMounted.
Возможно, у вас возникнет вопрос: что это за таинственный метод setup?
Если коротко, setup — просто функция, которая передаёт свойства и функции в шаблон. Мы описываем все реактивные и вычисляемые свойства, хуки жизненного цикла и всех наблюдателей в функции setup, а затем возвращаем их, чтобы использовать в шаблоне.
К тому, что мы не вернём из setup, доступа в шаблоне не будет.
Реактивное свойство count инициализируем с помощью функции ref. Она принимает примитив или объект и возвращает реактивную ссылку. Переданное значение будет сохранено в свойстве value созданной ссылки. Например, если мы хотим получить доступ к значению count, нам необходимо явно обратиться к count.value.
Так мы объявляем вычисляемое свойство double и функцию increment.
C помощью хука onMounted мы выводим в консоль сообщение после монтирования компонента для демонстрации такой возможности.
Чтобы свойства count и double и метод increment были доступны в шаблоне, возвращаем их из метода setup.
И вуаля! У нас есть доступ к свойствам и методам из setup, точно так же, как если бы они были объявлены через старый Options API.
Это простой пример, подобное можно было бы легко написать и с помощью Options API.
Но преимущество нового Composition API не столько в возможности писать код в другом стиле, сколько в возможностях, открываемых для повторного использования логики.
Переиспользование кода с Composition API
Давайте подробнее рассмотрим преимущества нового Composition API, например, для переиспользования кода. Сейчас, если мы хотим использовать какой-то кусок кода в нескольких компонентах, у нас есть два варианта: миксины (mixins) и слоты с ограниченной областью видимости (scoped slots). Оба варианта имеют свои недостатки.
Мы хотим извлечь функциональность счётчика и переиспользовать его в других компонентах. Вот пример, как это может быть сделано с помощью существующего и с помощью нового API.
Для начала рассмотрим реализацию с использованием миксинов.
Самая большая проблема такого подхода — мы ничего не знаем о том, что добавляется в наш компонент. Это затрудняет понимание и может приводить к коллизиям с существующими свойствами и методами.
Теперь рассмотрим слоты с ограниченной областью видимости.
При использовании слотов мы в точности знаем, к каким свойствам мы имеем доступ через директиву v-slot, что достаточно просто понять. Недостаток этого подхода в том, что мы можем получить доступ только к данным компонента Counter.
А теперь рассмотрим реализацию с использованием Composition API.
Выглядит гораздо элегантнее, не так ли? Мы не ограничены ни шаблоном, ни областью видимости и точно знаем, какие свойства счётчика доступны. И благодаря тому, что useCounter — просто функция, которая возвращает данные, в качестве приятного бонуса мы получаем автодополнение кода в редакторе. Здесь нет магии, поэтому редактор может помогать нам с проверкой типов и давать подсказки.
Лучше выглядит и использование сторонних библиотек. Например, если мы хотим использовать Vuex, то можем явно импортировать функцию useStore и не засорять прототип Vue свойством this.$store. Этот подход позволяет избавиться от дополнительных манипуляций в плагинах.
Если вы хотите узнать больше о Composition API и его применениях, я рекомендую прочитать документ, в котором команда Vue объясняет причины создания нового API и предлагает кейсы, в которых он пригодится. Также есть замечательный репозиторий с примерами использования Composition API от Thorsten Lünborg, одного из членов команды ядра Vue.
Изменения в конфигурировании и монтировании
В новом Vue есть другие важные изменения в том, как мы создаём и конфигурируем наше приложение. Давайте рассмотрим это на примере.
Сейчас мы используем глобальный объект Vue для конфигурирования и создания новых инстансов Vue. Любое изменение, сделанное нами в объекте Vue, будет затрагивать конечные инстансы и компоненты.
Рассмотрим, как это будет работает во Vue 3.
Как вы уже заметили, конфигурация относится к конкретному инстансу Vue, созданному с помощью createApp.
Это делает наш код более читабельным, снижает возможность появления неожиданных проблем со сторонними плагинами. Сейчас любая сторонняя библиотека, модифицирующая глобальный объект Vue, может повлиять на ваше приложение в неожиданном месте (особенно если это глобальный миксин), что невозможно во Vue 3.
Эти изменения обсуждаются в RFC, и возможно, в будущем реализация будет другой.
Фрагменты
Ещё одна крутая фича, на которую мы можем рассчитывать во Vue 3.
Что такое фрагменты?
В настоящий момент компонент может иметь только один корневой элемент, а это значит, что код ниже работать не будет.
Причиной является то, что инстанс Vue, скрывающийся за каждым компонентом, может быть прикреплён только к одному элементу DOM. Сейчас существует способ создать компонент с несколькими корневыми элементами: для этого необходимо написать компонент в функциональном стиле, которому не нужен собственный инстанс Vue.
Оказывается, такая же проблема существует и в React-сообществе, решена она была с помощью виртуального элемента Fragment.
Несмотря на то, что Fragment выглядит как обычный DOM-элемент, он виртуальный и не будет создаваться в DOM-дереве. С этим подходом мы можем использовать функциональность одного корневого элемента без создания лишнего элемента в DOM.
Сейчас вы можете использовать фрагменты и во Vue 2, но с помощью библиотеки vue-fragments, а во Vue 3 они будут работать из коробки!
Suspense
Еще одна отличная идея из экосистемы React, которая будет реализована во Vue 3, — это Suspense.
Suspense приостанавливает рендеринг компонента и отображает заглушку до выполнения определённых условий. На конференции Vue London Эван Ю вскользь затронул Suspense и показал API, который мы можем ожидать в будущем. Suspense-компонент будет иметь 2 слота: для контента и для заглушки.
Заглушка будет отображаться до тех пор, пока компонент не будет готов. Компонент Suspense также может ожидать загрузку асинхронного компонента или выполнения каких-то асинхронных действий в setup-функции.
Несколько v-models
v-model — это директива, с помощью которой можно использовать двусторонний биндинг. Мы можем передать реактивное свойство и изменить его внутри компонента.
Нам она хорошо известна по работе с элементами форм.
Но знали ли вы, что v-model можно использовать с любым компонентом? Под капотом v-model является лишь пробросом параметра value и прослушиванием события input.
Переписать предыдущий пример с использованием этого синтаксиса можно следующим образом:
Можно даже изменить названия свойства и события по умолчанию с помощью опции model:
Как видно, директива v-model может быть очень полезным «синтаксическим сахаром», если мы хотим использовать двусторонний биндинг в наших компонентах. К сожалению, на компонент может быть лишь одна v-model.
К счастью, во Vue 3 эта проблема будет решена. Мы сможем передать имя в v-model и использовать столько v-model, сколько необходимо.
Эти изменения обсуждаются в RFC, и возможно, в будущем реализация будет другой.
Portals
Порталы — это компоненты, созданные для рендера контента вне иерархии текущего компонента. Это тоже одна из возможностей, реализованных в React. В документации React порталы описываются следующим образом: «Порталы позволяют рендерить дочерние элементы в DOM-узел, который находится вне DOM-иерархии родительского компонента».
Порталы отлично подходят для реализации таких компонентов, как модальные окна, попапы и всех тех, которые необходимо отобразить поверх страницы.
При использовании порталов вы можете быть уверены, что стили родительского компонента не повлияют на дочерний. Это также избавит вас от грязных хаков с z-index.
Для каждого портала нам необходимо указать место назначения, в котором должен отображаться контент портала.
Ниже представлен вариант реализации на библиотеке portal-vue, которая добавляет порталы во Vue 2.
А во Vue 3 данная фича будет из коробки.
Новое API пользовательских директив
API пользовательских директив немного изменится во Vue 3, чтобы больше соответствовать жизненному циклу компонента. Создание директив станет более интуитивным, а значит, и более простым для понимания и изучения новичками.
Сейчас объявление пользовательской директивы выглядит так:
А во Vue 3 будет выглядеть так:
Несмотря на то, что это ломающие изменения, они могут быть использованы с совместимой сборкой Vue.
Этот API так же обсуждается и может измениться в будущем.
Резюме
Рядом со значительным нововведением — Composition API — мы можем найти несколько улучшений поменьше. Очевидно, что Vue движется в сторону улучшения опыта разработчика, к упрощению и интуитивизации API. Так же круто видеть, что команда Vue решила добавить в ядро фреймворка много идей, которые уже реализованы в сторонних библиотеках.
Список выше содержит только наиболее важные улучшения и изменения API. Если вам захотелось узнать и о других, загляните в репозиторий RFC.
Практическое введение в Composition API Vue 3
Composition API — это отличный способ делиться логикой приложения между компонентами в Vue.js. Вы сможете не только организовать повторяющиеся фрагменты кода в отдельные файлы, но и упростите их повторное использование.
Composition API позволяет сохранять реактивность переменных в общих фрагментах кода даже для приложений корпоративного размера, что может быть огромным достоинством по сравнению с реализациями в предыдущих версиях Vue. Согласно официальной документации, необходимость разработки Composition API обусловлена тем, что эффективное совместное использование кода разными компонентами вызывало проблемы в больших приложениях.
Хотя решения для выде л ения общих элементов, такие как миксин (mixin), компонент без рендеринга (renderless compontent) или HOC, существовали и прежде, ни одно из них не могло обеспечить столь высокую степень гибкости, как Composition API. Основным преимуществом этой новой функциональности является возможность одновременного извлечения элементов, которые прежде приходилось реализовывать для определенного компонента в данных, вычисляемых свойствах (computed) и методах (с помощью Options API). Рассмотрим краткий пример использования Composition API в реальных ситуациях.
В качестве первого шага создайте проект с помощью Vue.js (версия 3). Ради скорости я буду использовать для этой цели Vue Cli. По завершении проекта удалите компонент примера, он нам больше не понадобится. Уточните структуру проекта, в которую мы организуем код. Я помещаю свои компоненты в папку component под Src и одновременно создаю папку services, в которую упаковываю повторно используемый, но “бескомпонентный” код, реализующий бизнес-логику. Один файл содержит одну службу, например реализующую различные сортировки и фильтрации или http-вызовы.
Обычно мы не хотим описывать их как компоненты, их можно только правильно параметризовать, но мы хотим видеть данную логику в целом, как модуль в коде. Composition API как решение для реализации идеально вписывается в эту идею.
Composition API вводит новую часть в код компонента, называемую setup. Это функция, которая может иметь 2 параметра: контекст (context) и свойства (props). Внутри setup мы можем реализовать сегменты, которые написали в разделах данных, вычисляемых свойств (computed) и методов, используя известный ранее API Options. Здесь мы можем определить внутреннее состояние и функции компонента, а также здесь использовать общие фрагменты кода, которые я называю службами (services).
Во многих проектах мне нужны таблицы, которые можно отсортировать по столбцам в порядке возрастания или убывания. Мы создадим две таблицы, которые будут использовать одну и ту же службу направления. Это отличный реальный пример эффективности идеи Composition API.
Конечно, в корпоративном проекте нам пришлось бы передать всю табличную логику на аутсорсинг общему компоненту таблицы, который затем использует службу сортировки. Но мы не будем этого делать сейчас, потому что статья задумана для представления Composition API, которого будет достаточно для извлечения служебного кода из таблиц.
Компонент агрегации приложения HomePage отображает только две таблицы: в одной перечислены пользователи, а в другой — продукты. Composition API позволяет создавать операцию сортировки как отдельную службу, где при необходимости можно работать с реактивными значениями, которые затем можно сделать доступными в компонентах, использующих эту службу.
В этом примере я сохраню направление сортировки в собственной реактивной переменной службы. Я печатаю это значение порядка в обоих табличных компонентах в надписях на кнопках под данными. Я буду изменять порядок сортировки только и исключительно внутри службы сортировки четко видимым образом и когда это необходимо, компонент будет немедленно уведомлен об этом изменении, доказывая наличие реактивности.
Конечный результат
Компонент HomePage содержит две таблицы (и несколько строк кода css для выделения таблиц):
Компоненты ProductTable и UserTable
Компонент ProductTable показывает простую таблицу с 3 столбцами и кнопкой для сортировки внизу. Он определяет строки данных для простоты из строки 25.
Строка 35: выполняется сортировка с этой службой “во время загрузки” компонента (см. методы жизненного цикла vue 3).
Строка 8: это состояние может быть использовано в шаблоне непосредственно.
В службе сортировки нет ничего особенного, это просто очень простая функция. Она может сортировать заданный массив данных по свойству названия содержимого. Я не проверяю входные значения, потому что это не имеет значения с точки зрения примера Composition API. Важными сегментами являются реактивное состояние внутри службы (или функции) и возвращаемое значение в конце конструкции.
Помните: вы должны вернуть ВСЕ (функции, переменные и т. д.) из службы сортировки, чтобы сделать ее доступной на уровне компонента.
# Введение
# Почему появился Composition API?
Прежде чем приступать к изучению этого раздела документации необходимо понимать как базовые основы Vue, так и принципы создания компонентов.
Создание компонентов Vue позволяет извлекать повторяющиеся части интерфейса, вместе со связанной функциональностью, в переиспользуемые части кода. Этот подход добавляет приложению достаточно много с точки зрения удобства обслуживания и гибкости. Однако, коллективный опыт показал, что этого всё ещё может быть недостаточно, если приложение становится действительно большим — когда счёт идёт на несколько сотен компонентов. Когда приходится работать с такими большими приложениями — возможность разделения и переиспользования кода становится крайне важна.
Представим, что в приложении есть компонент, который отображает список репозиториев конкретного пользователя. Поверх него, нужно реализовать функциональность поиска и фильтрации. Компонент, управляющий подобным отображением, может выглядеть так:
Этот компонент имеет несколько обязанностей:
Пример большого компонента, в котором сгруппированы по цвету его логические блоки.
Подобная фрагментация усложняет понимание и поддержание таких сложных компонентов. Разделение по опциям делает менее заметными логические блоки используемые в них. Кроме того, при работе над одной логической задачей приходится постоянно «прыгать» между блоками в поисках соответствующего кода.
Было бы удобнее, если соответствующий логическому блоку код можно разместить рядом. И это именно то, чего позволяет добиться Composition API.
# Основы Composition API
# Опция компонента setup
Опция setup должна быть функцией, которая принимает аргументами props и context (о которых подробнее поговорим дальше). Кроме того, всё что возвращается из функции setup будет доступно для остальных частей компонента (вычисляемых свойств, методов, хуков жизненного цикла и т.д.), а также в шаблоне компонента.
Добавим setup в компонент:
Извлечём логику первого логического блока (отмеченной как «1» в исходном примере).
Начнём с самых очевидных частей:
Начало положено! Пока что ещё не всё работает, потому что переменная repositories не реактивна. С точки зрения пользователя, список репозиториев будет оставаться пустым. Давайте это исправим!
# Реактивные переменные с помощью ref
Наличие объекта-обёртки вокруг любого значения позволяет безопасно использовать его в любой части приложения, не беспокоясь о потере реактивности где-то по пути.
Другими словами, ref создаёт реактивную ссылку к значению. Концепция работы со ссылками используется повсеместно в Composition API.
Возвращаясь к примеру, создадим реактивную переменную repositories :
Готово! Теперь каждый вызов getUserRepositories будет изменять repositories и обновлять вид блока, чтобы отобразить изменения. Компонент станет выглядеть так:
Начнём с хука жизненного цикла.
# Использование хуков жизненного цикла внутри setup
Эти функции принимают аргументом коллбэк, который выполнится при вызове компонентом хука жизненного цикла.
Добавим его в функцию setup :
# Отслеживание изменений с помощью watch
Простой пример, чтобы понять как это работает:
Эквивалент при использовании Options API:
Более подробную информацию о watch можно найти в продвинутом руководстве.