Поширені запитання по Композиційному API
TIP
Ці запитання передбачають попередній досвід роботи з Vue, зокрема, досвід роботи з Vue 2 при переважному використанні Опційного API.
Що таке Композиційний API?
Композиційний API — це набір API, який дозволяє нам створювати компоненти Vue, використовуючи імпортовані функції замість оголошення опцій. Це загальний термін, який охоплює такі API:
Реактивний API, наприклад,
ref()
таreactive()
, які дозволяють нам безпосередньо створювати реактивний стан, обчислювальний стан та спостерігачів.Хуки життєвого циклу, наприклад,
onMounted()
таonUnmounted()
, які дозволяють нам програмно підключатися до життєвого циклу компонента.Впровадження залежностей, тобто
provide()
таinject()
, які дозволяють нам використовувати систему впровадження залежностей Vue під час використання реактивного API.
Композиційний API є вбудованим функціоналом Vue 3 та Vue 2.7. Для старих версій Vue 2 використовуйте офіційно підтримуваний плагін @vue/composition-api
. У Vue 3, він також переважно використовується разом із синтаксисом <script setup>
в одно-файлових компонентах. Ось базовий приклад компонента, який використовує Композиційний API:
vue
<script setup>
import { ref, onMounted } from 'vue'
// реактивний стан
const count = ref(0)
// функції, які змінюють стан і запускають оновлення
function increment() {
count.value++
}
// хуки життєвого циклу
onMounted(() => {
console.log(`Початкова кількість є ${count.value}.`)
})
</script>
<template>
<button @click="increment">Кількість: {{ count }}</button>
</template>
Незважаючи на стиль API, заснований на композиції функцій, Композиційний API НЕ є функціональним програмуванням. Композиційний API базується на мінливій, детальній парадигмі реактивності Vue, тоді як функціональне програмування наголошує на незмінності.
Якщо ви зацікавлені в тому, щоб дізнатися, як використовувати Vue з Композиційним API, ви можете встановити налаштування API для цього сайту на Композиційне API за допомогою перемикача вгорі лівої бічної панелі, а потім переглянути посібник із самого початку.
Чому композиційне API?
Краще логічне повторне використання
Основна перевага Composition API полягає в тому, що він дає змогу чистого та ефективного повторного використання логіки у формі Композиційних функцій. Він усуває всі недоліки міксинів, основного механізму повторного використання логіки для Опційного API.
Можливість повторного використання логіки Композиційного API призвела до появи таких вражаючих проєктів спільноти, як VueUse, колекція композиційних утиліт, яка постійно зростає. Він також служить чистим механізмом для легкої інтеграції сторонніх служб або бібліотек із збереженням стану в систему реактивності Vue, наприклад, незмінні дані, машини станів, та RxJS.
Більш гнучка організація коду
Багатьом користувачам подобається, що ми пишемо впорядкований код за замовчуванням за допомогою Опційного API: усе має своє місце залежно від того, до якої опції воно відноситься. Однак Опційний API накладає серйозні обмеження, коли логіка одного компонента перевищує певний поріг складності. Це обмеження є особливо помітним у компонентах, які мають справу з кількома логічними завданнями, що ми могли бачити на власні очі в багатьох виробничих середовищах застосунків на Vue 2.
Візьмемо для прикладу компонент провідника папок із GUI Vue CLI: цей компонент відповідає за такі логічні завдання:
- Відстеження поточного стану папки та відображення її вмісту
- Керування навігацією папками (відкриття, закриття, оновлення...)
- Керування створенням нової папки
- Перемикання показу лише улюблених папок
- Перемикання показу прихованих папок
- Обробка змін поточного робочого каталогу
Оригінальна версія компонента була написана в Опційному API. Якщо ми надамо кожному рядку коду колір на основі логічної задачі, з якою він має справу, це виглядатиме ось так:
Зверніть увагу, як код, який має справу з тим самим логічним завданням, змушений бути розділений на різні опції, розташовані в різних частинах файлу. У компоненті, що складається з кількох сотень рядків, розуміння та навігація по одній логічній задачі потребує постійного прокручування файлу вгору та вниз, що робить це набагато складнішим, ніж повинно бути. Крім того, якщо ми коли-небудь маємо намір витягнути логічну проблему утиліту з повторного використання, знадобиться чимало роботи, щоб знайти та витягти потрібні фрагменти коду з різних частин файлу.
Ось той самий компонент до і після рефакторінгу в Композиційне API:
Зверніть увагу, як код, пов'язаний з одним логічним завданням, тепер можна згрупувати разом: нам більше не потрібно переходити між різними опційними блоками під час роботи над конкретним логічним завданням. Крім того, тепер ми можемо перемістити групу коду у зовнішній файл із мінімальними зусиллями, оскільки нам більше не потрібно перемішувати код, щоб витягти їх. Це зменшення складнощів для рефакторингу є ключовим для довгострокового обслуговування великих кодових баз.
Краще визначення типів
Останніми роками все більше розробників інтерфейсу використовують TypeScript, оскільки це допомагає нам писати більш надійний код, вносити зміни з більшою впевненістю та забезпечує чудовий досвід розробки за підтримки IDE. Однак Options API, спочатку задуманий у 2013 році, був розроблений без урахування визначення типів. Нам довелося реалізувати певну абсурдно складне перетворення типів, щоб змусити визначення типів працювати з Опційним API. Навіть з усіма цими зусиллями, визначення типів для Опційного API все ще може ламатися для міксинів і впровадження залежностей.
Це спонукало багатьох розробників, які хотіли використовувати Vue із TS, схилитися до Класового API на базі vue-class-component
. Однак API на основі класів значною мірою покладається на декоратори ES, функціонал мови програмування, який був лише пропозицією на етапі 2 під час розробки Vue 3 у 2019 році. Ми вважали надто ризикованим створювати офіційний API на основі нестабільної пропозиції. З тих пір пропозиція декораторів пройшла ще один повний перегляд і, нарешті, досягла третього етапу в 2022 році. Крім того, у Класовому API є проблеми з логікою повторного використання та організаційні обмеження, подібні до Опційного API.
Для порівняння, Композиційний API використовує здебільшого прості змінні та функції, які, природно дружні до типів. Код, написаний за допомогою Композиційного API, може похвалитися повним визначенням типів без потреби написання підказок до них вручну. У більшості випадків код Композиційний API виглядатиме майже ідентичним і в TypeScript, і в простому JavaScript. Це також дає змогу користувачам простого JavaScript отримати вигоду від часткового визначення типів.
Менший пакет на виробництві і менше накладних витрат
Код, написаний з Композиційним API та <script setup>
, також ефективніший і зручніший для мінімізації, ніж еквівалент Опційного API. Це пояснюється тим, що шаблон у компоненті <script setup>
скомпільовано як функцію, вбудовану в ту саму область коду <script setup>
. На відміну від доступу до властивостей із this
, скомпільований код шаблону може напряму отримувати доступ до змінних, оголошених у <script setup>
, без екземпляра проксі між ними. Це також призводить до кращої мініфікації, оскільки всі імена змінних можна безпечно скоротити.
Зв'язок з Опційним API
Компроміси
Деякі користувачі, які перейшли з Опційного API, виявили, що їхній код на Композиційному API менш організований, і дійшли висновку, що Композиційний API "гірший" з точки зору організації коду. Користувачам з такою думкою ми рекомендуємо поглянути на проблему з іншої точки зору.
Це правда, що Композиційний API більше не надає "запобіжних рейок", які спрямовують вас до розміщення коду у відповідних сегментах. Натомість ви отримуєте код авторського компонента, як би ви писали на звичайному JavaScript. Це означає, що ви можете і повинні застосовувати будь-які найкращі методи організації коду до свого коду на Композицінйому API, як і під час написання звичайного JavaScript. Якщо ви можете написати добре організований JavaScript, ви також повинні вміти писати добре організований код на Композиційному API.
Опційний API дійсно дозволяє вам "менше думати" під час написання коду компонентів, тому багато користувачів люблять його. Однак, зменшуючи розумові накладні витрати, це також обмежує вас у встановленому шаблоні організації коду без аварійного люка, що може ускладнити рефакторинг або покращення якості коду у більш масштабних проєктах. У цьому відношенні Композиційний API забезпечує кращу довгострокову масштабованість.
Чи охоплює Композиційний API усі випадки використання?
Так, з точки зору логіки стану. Під час використання Composition API може знадобитися лише кілька параметрів: props
, emits
, name
і inheritAttrs
.
TIP
Починаючи з версії 3.3, ви можете безпосередньо використовувати defineOptions
в <script setup>
, щоб установити назву компонента або властивість inheritAttrs
Якщо ви маєте намір використовувати виключно Композциційний API (разом із параметрами, згаданими вище), ви можете скоротити кілька кілобайт у своєму виробничому пакеті за допомогою прапорця під час компіляції, який видаляє код, пов'язаний з Опційним API, із Vue. Зауважте, що це також впливає на компоненти Vue у ваших залежностях.
Чи можу я використовувати обидва API разом в тому ж самому компоненті?
Так. Ви можете використовувати Композиційний API через опцію setup()
у компоненті на Опційному API.
Однак ми рекомендуємо робити це лише якщо у вас є кодова база на Опційному API, яку потрібно інтегрувати з новими функціями / зовнішніми бібліотеками, написаними за допомогою Композиційного API.
Чи буде Опційний API застарілим?
Ні, ми не плануємо це робити. Опційний API є невід'ємною частиною Vue і тому багато розробників люблять його. Ми також розуміємо, що багато переваг Композиційного API стають доречними лише у великих проєктах, а Опційний API залишається надійним вибором для багатьох сценаріїв низької та середньої складності.
Відносини з Класовим API
Ми більше не рекомендуємо використовувати Класовий API із Vue 3, враховуючи, що Композиційний API забезпечує чудову інтеграцію TypeScript із додатковим повторним використанням логіки та перевагами організації коду.
Порівняння з хуками React
Композиційний API надає той самий рівень можливостей логічної композиції, що й хуки React, але з деякими важливими відмінностями.
Хуки React викликаються повторно щоразу, коли компонент оновлюється. Це створює низку застережень, які можуть заплутати навіть досвідчених розробників React. Це також призводить до проблем з оптимізацією продуктивності, які можуть серйозно вплинути на досвід розробки. Ось кілька прикладів:
Хуки чутливі до порядку виклику і не можуть бути умовними.
Змінні, оголошені в компоненті React, можуть бути захоплені замиканням хука та стати "застарілими", якщо розробнику не вдасться передати правильний масив залежностей. Це призводить до того, що розробники React покладаються на правила ESLint, щоб забезпечити передачу правильних залежностей. Однак правило часто є недостатньо розумним і надмірно компенсує правильність, що призводить до непотрібних недійсностей та головного болю в окремих випадках.
Дорогі обчислення вимагають використання
useMemo
, що, знову таки, вимагає передачі правильного масиву залежностей вручну.Обробники подій, які передані дочірнім компонентам, викликають непотрібні дочірні оновлення за замовчуванням і вимагають явного
useCallback
як оптимізацію. Це майже завжди потрібно, і знову вимагає правильного масиву залежностей. Нехтування цим призводить до надмірного рендерингу застосунків за замовчуванням і може спричинити проблеми з продуктивністю, без уявлення, що проблема може бути у цьому.Проблема застарілого замикання в поєднанні з функціоналом Concurrent ускладнює визначення того, коли запускається фрагмент коду хуків, і робить роботу обтяжливою зі станом, що змінюється, і який має зберігатися між рендерами (через
useRef
).
Для порівняння, Vue Композиційний API:
Викликає код
setup()
або<script setup>
лише один раз. Завдяки цьому код більш інтуїтивний і краще узгоджується з ідіомами використання JavaScript, оскільки немає застарілих замикань, про які варто турбуватися. Виклики Композиційного API також не залежать від порядку викликів і можуть бути умовними.Система реактивності середовища виконання Vue автоматично збирає реактивні залежності, що використовуються в обчислюваних властивостях та спостерігачах, тому немає необхідності оголошувати залежності вручну.
Не потрібно вручну кешувати функції зворотного виклику, щоб уникнути непотрібних дочірніх оновлень. Загалом, детальна система реактивності Vue гарантує, що дочірні компоненти оновлюються лише тоді, коли вони цього потребують. Ручна оптимізація дочірніх оновлень рідко турбує розробників Vue.
Ми визнаємо креативність хуків React, і це є головне джерело натхнення для Композиційного API. Однак є згадані вище проблеми, які існують у його конструкції, і ми помічаємо, що модель реактивності Vue дає спосіб їх обійти.