Когда использовать новое Composition API во Vue (а когда нет)
Перевод статьи Anthony Gore — When To Use The New Vue Composition API (And When Not To)
Новое Composition API вызвало немало споров, когда оно было впервые анонсировано командой Vue. Но теперь, когда пыль осела и у нас появилась возможность его попробовать, большинство из нас может увидеть, что у нее огромный потенциал.
Но, как и любой инструмент программирования, мы можем ожидать, что оно будет иметь как преимущества, так и недостатки. Поэтому сейчас я думаю не о том, как его использовать, а о том, когда его следует использовать.
В RFC сказано:
«проблемы, на решение которых направлен API композиции, появляются главным образом в крупномасштабных приложениях».
Но полезно ли оно для небольших приложений? Или его следует избегать?
В этой статье я поделюсь своими мыслями и постараюсь сформулировать руководящий принцип, который может быть вам полезным.
Содержание:
- Мотивирующий пример
- Модель композиции компонентов
- Многофункциональные компоненты
- Отделение логики
- Обычные компоненты и Composition API
- Почему не оба
- Завершение с руководящим принципом
Мотивирующий пример
В RFC приводится мотивирующий пример большого компонента со многими функциями, которые стали громоздкими в рамках API опций.
Затем RFC показывает, как рефакторинг этого компонента для использования Composition API позволил упорядочить функциональность по функциям, а не по опциям, тем самым улучшая читабельность.
Хотя этот пример прекрасно иллюстрирует необходимость в Composition API, он несколько смутил меня, потому что это пример нетипичного большого и сложного компонента.
Будут ли получены те же преимущества с меньшими, «обычными» компонентами, с которыми я чаще всего сталкиваюсь? Чтобы ответить на этот вопрос, я думаю, что стоит посмотреть на условия, при которых компонент становится таким большим и сложным.
Модель композиции компонентов
Наряду с реакционной способностью модель композиции компонентов (component composition model) является определяющей характеристикой Vue.js.
Хотя в документах явно не говорится об этом, подразумевается, что в этой модели существует взаимно-однозначное отношение между компонентом и «функцией».
Например, простой компонент состоящий из одной кнопки, подобный следующему, обычно состоит из одной функции — для обработки полученных кликов.
MyButton.vue
<template> <button @click="doStuff">Click me</button> </template>
Но этот компонент впоследствие может быть расширен, чтобы включать в себя несколько функций. Например, что если мы решили сделать так, чтобы эта кнопка вызывала выпадающий список?
Сначала мы могли бы добавить раскрывающийся список в структуру шаблона и компонента, но затем наше понимание модели компоновки компонентов снова вступило бы в силу, и мы были бы вынуждены абстрагировать новую функцию в подкомпонент, тем самым восстанавливая соотношение компонентов и функций.
MyButton.vue
<template> <button @click="doStuff"> Click me <drop-down v-bind:some-prop="..." /> </button> </template>
Многофункциональные компоненты
Но бывают случаи, когда более сложные функциональные возможности не вписываются в модель композиции компонентов.
Хорошим примером этого является валидируемая форма ввода. Они имеют несколько функций, которые нельзя легко делегировать в подкомпоненты, поскольку все функции сложно связаны с одним и тем же элементом пользовательского интерфейса.
В этом примере вы можете получить две различные функции для компонента — обработку ввода и проверку ввода. Такой компонент будет намного лучше организован, если его разбить по функциям с использованием Composition API.
ValidatedFormInput.vue
useHandleInput() { ... } useValidateInput() { ... } export default { setup () { return { ...useHandleInput(), ...useValidateInput() } }, ... }
Отделение логики
Иногда мы хотим создать варианты для компонента. Например, мы можем захотеть, чтобы кнопка имела разные цвета при использовании в разных формах на нашем сайте.
Модель компоновки компонентов предоставляет способ сделать это — просто использовав функциональность шаблона, управляемого состоянием, передаваемым через props. Другой вариант может быть реализован с помощью слотов.
SimpleButtonCustomColor.vue
<template> <button @click="doStuff" :classes="{ color }"> Click me </button> </template> <script> export default { props: { color: String } } </script>
Тем не менее, такой шаблон не будет хорошо масштабироваться. По мере того, как вариаций будет становится все больше и больше или если логика в компоненте будет усложняться, то и сам компонент будет усложняться.
В этом случае лучшим способом его развития будет абстрагирования логики. Composition API для этого подходит лучше всего, потому что намного проще абстрагировать код, который уже организован по функциям.
Например, допустим, вы создали компонент кнопки submit, который будете использовать в различных формах на своем сайте. Логика в шаблоне достигла своего предела масштабирования, поэтому Composition API позволит вам абстрагировать общую логику в функцию композиции, которая, в отличие от миксина, может очень элегантно использоваться несколькими компонентами:
useSubmitButton.js
export default { handleSubmit() { ... }, ... }
SubmitButtonFullForm.vue
// General feature import useSubmitButton from "./useSubmitButton.js"; // Specific feature function useFullFormButton() { ... } export default { setup() { return { ...useSubmitButton(), ...useFullFormButton() } } }
SubmitButtonInlineForm.vue
// General feature import useSubmitButton from "./useSubmitButton.js"; // Specific feature function useInlineFormButton() { ... } export default { setup() { return { ...useSubmitButton(), ...useInlineFormButton() } } }
Обычные компоненты и Composition API
Мотивирующий пример из RFC является нетипичным в том смысле, что это сложный многофункциональный компонент. Также возможно, что часть его логики повторно используется и в других компонентах приложения. Эти особенности делают его идеальным кандидатом на Composition API.
Но когда компоненты являются обычными (однофункциональными и не требуют логической абстракции для повторного использования), что может предложить Composition API?
Кажется, нам не следует применять Composition API вслепую, так как RFC указывает на несколько недостатков, включая путаницу между функциями refs и reactive, а также дополнительный шаблон функции setup.
Если в обычном компоненте модель компоновки компонентов (component composition model) не достигла своих пределов, Composition API не будет решает никаких проблем, а только подвергает компонент указанным недостаткам.
Но не используйте это как жесткое правило, так как Composition API также имеет некоторые дополнительные преимущества:
- Лучшая совместимость с TypeScript
- Лучший доступ к функциям более низкого уровня, таким как реактивность
- Позволяет легко интегрировать предварительно упакованные функции, например, useWeb
Почему не оба
На практике любое отдельное приложение, скорее всего, будет иметь некоторые компоненты, которые могут извлечь выгоду из Composition API, а также многие другие, которые не получат ни какой выгды использования.
Я просмотрел некоторые из приложений Vue 2, над которыми я ранее работал (в основном они были небольшие), и обнаружил, что только 10-20% компонентов были многофункциональными или использовали миксины и могли бы воспользоваться Composition API.
Так что я не думаю что это должно быть бинарным выбором … почему бы просто не использовать оба API вместе?
С одной стороны, это не очень хорошая идея, так как переключение между двумя API увеличит когнитивную нагрузку. Кроме того, может случиться так, что у вас будет генерироваться меньшая по размеру сборка проекта, если решите использовать только один из двух API.
Но иногда я все же думаю о компромисе и допускаю использование обоих API вместе, когда это необходимо.
Завершение с руководящим принципом
Composition API все еще технически предложенная функция, поэтому она может измениться, и даже если не будет ни каких изменений, я уверен, что со временем будет реализовано много интересных возможностей.
Но я обещал руководящий принцип, так что вот он:
Composition API можно рассматривать так же, как и Vuex — это может быть полезным инструментом, но он требует затрат, поэтому его не следует использовать бездумно. Если вы не уверены, что оно вам нужно, то скорее всего, оно вам не нужно.
Даже если вы не согласны с этим, я надеюсь, что вышеизложенное было полезной пищей для размышлений, и мне было бы интересно услышать ваше мнение о том, когда следует использовать API композиции. (в блоге автора статьи)
Спасибо за работу. Что скажете про свявку Vue + Django?