Vue
Vue — це фреймворк, побудований навколо системи реактивності, яка стежить за тим, що читає ваш код. Ви не оголошуєте залежностей і не кажете, що змінилося: читання значення під час рендеру реєструє цей рендер як залежний, а запис значення перезапускає рівно цих залежних. Більшість того, що вирізняє Vue на практиці, випливає з цього одного механізму.
- Реактивність
- На проксі, з відстеженням
- Одиниця коду
- Однофайловий компонент
- Два API
- Composition · Options
Залежність створює читання
Vue загортає ваш стан у проксі — об’єкт, здатний спостерігати кожне читання й кожен запис своїх властивостей. Ця єдина спроможність і є всією системою, а решта — її наслідки.
Поки виконується ефект — рендер компонента, обчислюване значення, watcher, — Vue знає, який ефект зараз активний. Кожна прочитана під час цього виконання властивість записує ефект на себе. Це відстеження. Пізніше, коли у властивість пишуть, Vue перезапускає ефекти, записані саме на цю властивість, і більше нічого. Це запуск.
Ціна проявляється однією конкретною пасткою. Реактивність живе на проксі, а не на значеннях усередині, тож витягання значення розриває зв’язок: const { count } = props копіює число, і копія ніколи не оновиться. Саме тому існує ref — він кладе значення в об’єкт із властивістю .value, тож передавання цієї коробки зберігає реактивність. toRefs робить те саме для об’єкта, який ви хочете розкласти.
Суфікс .value — те, що не подобається новачкам, і його варто зрозуміти, а не дратуватися: це видимий шов, де звичайне значення стає відстежуваним. У шаблонах Vue розгортає ref автоматично, тож він трапляється лише в скрипті, а в однофайлових компонентах компіляторне перетворення прибирає й більшість цього.
Однофайлові компоненти й два API
Компонент Vue — це зазвичай один файл .vue із трьома блоками: шаблон, скрипт і стилі. Аргумент за те, щоб тримати їх разом, у тому, що вони змінюються разом — правити компонент означає правити всі три, — а аргумент проти, що це змішує мови в одному файлі, стабільно програє вже десять років.
Блок стилів приймає атрибут scoped, і це справді корисний типовий вибір: Vue додає елементам цього компонента згенерований атрибут і обмежує кожен селектор ним, тож правило не може втекти в інший компонент. Це та сама локальність, заради якої зазвичай упроваджують методології CSS, — тільки її безкоштовно дає компілятор.
Composition API
- Код згрупований за фічею, а не за типом опції
- Логіка виноситься у звичайні функції — composables
- Типи виводяться природно, TypeScript не потребує допомоги
- Типовий вибір для нового коду
Options API
- Код згрупований у data, computed, methods, watch
- Перевикористання через міксини, походження яких важко відстежити
- Легша перша година; важчий десятий компонент
- Підтримується, поширений у наявному коді
Різниця важить у масштабі, а не на старті. У компоненті з трьома темами Options API розкидає кожну по чотирьох секціях, тож зрозуміти «як тут працює пошук» означає прочитати чотири місця й утримати їх разом; Composition API дозволяє трьом темам лежати трьома блоками й будь-яку з них винести в composable, який зможе імпортувати інший компонент. Підтримуються обидва; новий код має бути на Composition.
Computed чи watch
Це рішення розробники на Vue помиляють найчастіше, і в нього є чисте правило. computed виводить значення: він кешується, перераховується лише коли змінюється щось прочитане ним, і має бути без побічних дій. watch реагує на зміну дією: викликом API, записом у сховище, запуском анімації.
Перевірка — одне питання: ви створюєте значення чи виконуєте дію? Watcher, що завершується присвоєнням в інший шматок стану, майже завжди є computed, написаним довгим шляхом: він спрацьовує на такт пізніше, може зациклитися, якщо два watcher пишуть у джерела один одного, і робить зв’язок між двома значеннями невидимим у коді.
Те саме правило поширюється на весь фреймворк. v-if прибирає елемент із DOM, а v-show перемикає його CSS-властивість display, тож v-if коштує на кожному перемиканні, а v-show — один раз при монтуванні; вибір залежить від того, як часто це перемикається. А v-for потребує :key із тієї самої причини, що й React: без стабільної ідентичності Vue перевикористає вузли DOM для не тих елементів, і стан опиниться не в тому рядку.
Що йде в комплекті
Vue стоїть між React і Angular за обсягом того, що вирішує за вас. Це не бібліотека, що лишає все відкритим, і не фреймворк, що постачає всю архітектуру застосунку. Він має невелику кількість офіційних пакетів, і оскільки вони офіційні, екосистема сходиться на них, а не розсипається.
- Vue Router — офіційний маршрутизатор, тож проєкт на Vue не починається з порівняння роутерів.
- Pinia — офіційне сховище, достатньо мале, щоб узяти його заради одного спільного значення не було надміром.
- Nuxt — метафреймворк для конвенцій маршрутизації, серверного рендерингу, завантаження даних і розгортання.
- Сама система реактивності опублікована окремо і працює взагалі без компонентів.
Останній пункт вартий хвилини. @vue/reactivity — окремий пакет: ref, обчислювані значення й ефекти без жодного рендерингу. Це чесний сигнал про те, де центр ваги фреймворку: шар компонентів побудований на системі реактивності, а не навпаки.
Vue проти React
| Питання | Vue | React |
|---|---|---|
| Як стають відомі залежності? | Виявляються читанням | Оголошуються, перевіряє лінтер |
| Що перезапускається при зміні? | Лише ефекти, що це читали | Компонент і його піддерево |
| Як пишеться вигляд? | Шаблон, який аналізує компілятор | JSX — звичайний JavaScript |
| Хто визначає архітектуру? | Офіційні роутер і сховище | Ви, щоразу |
| Де губиться стан? | Розкладання реактивного об’єкта | Зміна на місці замість заміни |
Жодна колонка не є вироком. Шаблонний підхід дає компілятору більше знань — він бачить, які частини вигляду статичні, і пропускає їх узагалі, а React мусить робити цю роботу під час виконання, — тоді як JSX є просто JavaScript, тож усе, що виражається мовою, виражається й у вигляді. Обирайте за двома речами, що справді різняться для команди: чи хочете ви отримати конвенції готовими і з якого пулу досвідчених розробників можете наймати.
Як це виявляється в реальній поставці
Репутація Vue як доступного фреймворку заслужена й трохи оманлива. Перший день справді легший: шаблон схожий на HTML, реактивність робить очікуване, і немає масиву залежностей, у якому можна помилитися. Те, що потребує уваги, приходить пізніше й дуже конкретне: треба точно знати, де реактивність зберігається, а де губиться, бо збій тихий. Розкладання реактивного об’єкта нічого не кидає — значення просто перестає оновлюватися, і баг виглядає як проблема рендерингу.
Де він вироджується
- Розкладання реактивного об’єкта чи пропсів тихо від’єднує значення від системи.
- Watcher, що присвоює в інший стан, — це computed, який спрацьовує на такт пізніше.
- Змішування Composition і Options API в одному компоненті без заявленої причини.
v-ifіv-forна одному елементі — пріоритет тут не такий, як більшість припускає.- Зміна пропа з дитини ламає односторонній потік, на який спирається фреймворк.
provide/injectяк глобальна змінна ховає, звідки взялося значення.- Глибоко реактивні великі списки: робота проксі тут реальна, а відповіддю був
shallowRef.
Коли це застосовувати
Застосовуйте, коли
- Ви хочете офіційні відповіді для маршрутизації й стану, а не вправу з порівняння.
- У команді є люди, які пишуть більше розмітки, ніж JavaScript, — шаблони пасують цій формі.
- Скоуповані стилі за замовчуванням знімуть методологію CSS, яку інакше довелося б упроваджувати.
- Вам потрібні точкові оновлення без ручного налаштування того, що перерендерюється.
Уникайте, коли
- Локальний ринок праці переважно React, і команда змінюватиметься.
- Проєкту потрібна екосистема бібліотек, яка сьогодні існує лише для React.
- Сторінка майже без стану — реактивний механізм стане накладною витратою без застосування.
- Ніхто не вивчить, де губиться реактивність, — тихі відмови стануть важкими в підтримці.
Було корисно?
Поділіться з тим, хто працює над тією ж задачею.