РозробкаБудь-який рівень

Vue

Vue — це фреймворк, побудований навколо системи реактивності, яка стежить за тим, що читає ваш код. Ви не оголошуєте залежностей і не кажете, що змінилося: читання значення під час рендеру реєструє цей рендер як залежний, а запис значення перезапускає рівно цих залежних. Більшість того, що вирізняє Vue на практиці, випливає з цього одного механізму.

Реактивність
На проксі, з відстеженням
Одиниця коду
Однофайловий компонент
Два API
Composition · Options

Залежність створює читання

Vue загортає ваш стан у проксі — об’єкт, здатний спостерігати кожне читання й кожен запис своїх властивостей. Ця єдина спроможність і є всією системою, а решта — її наслідки.

Vue загортає стан у проксі. Поки виконується ефект — рендер, computed чи watcher, — кожна прочитана властивість записує цей ефект як свою залежність; це відстеження. Коли у властивість пишуть, перезапускаються лише ті ефекти, які її записали; це запуск. Більше нічого не перевіряється — тому 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

ПитанняVueReact
Як стають відомі залежності?Виявляються читаннямОголошуються, перевіряє лінтер
Що перезапускається при зміні?Лише ефекти, що це читалиКомпонент і його піддерево
Як пишеться вигляд?Шаблон, який аналізує компіляторJSX — звичайний JavaScript
Хто визначає архітектуру?Офіційні роутер і сховищеВи, щоразу
Де губиться стан?Розкладання реактивного об’єктаЗміна на місці замість заміни

Жодна колонка не є вироком. Шаблонний підхід дає компілятору більше знань — він бачить, які частини вигляду статичні, і пропускає їх узагалі, а React мусить робити цю роботу під час виконання, — тоді як JSX є просто JavaScript, тож усе, що виражається мовою, виражається й у вигляді. Обирайте за двома речами, що справді різняться для команди: чи хочете ви отримати конвенції готовими і з якого пулу досвідчених розробників можете наймати.

Як це виявляється в реальній поставці

Репутація Vue як доступного фреймворку заслужена й трохи оманлива. Перший день справді легший: шаблон схожий на HTML, реактивність робить очікуване, і немає масиву залежностей, у якому можна помилитися. Те, що потребує уваги, приходить пізніше й дуже конкретне: треба точно знати, де реактивність зберігається, а де губиться, бо збій тихий. Розкладання реактивного об’єкта нічого не кидає — значення просто перестає оновлюватися, і баг виглядає як проблема рендерингу.

Де він вироджується

  • Розкладання реактивного об’єкта чи пропсів тихо від’єднує значення від системи.
  • Watcher, що присвоює в інший стан, — це computed, який спрацьовує на такт пізніше.
  • Змішування Composition і Options API в одному компоненті без заявленої причини.
  • v-if і v-for на одному елементі — пріоритет тут не такий, як більшість припускає.
  • Зміна пропа з дитини ламає односторонній потік, на який спирається фреймворк.
  • provide / inject як глобальна змінна ховає, звідки взялося значення.
  • Глибоко реактивні великі списки: робота проксі тут реальна, а відповіддю був shallowRef.

Коли це застосовувати

Застосовуйте, коли

  • Ви хочете офіційні відповіді для маршрутизації й стану, а не вправу з порівняння.
  • У команді є люди, які пишуть більше розмітки, ніж JavaScript, — шаблони пасують цій формі.
  • Скоуповані стилі за замовчуванням знімуть методологію CSS, яку інакше довелося б упроваджувати.
  • Вам потрібні точкові оновлення без ручного налаштування того, що перерендерюється.

Уникайте, коли

  • Локальний ринок праці переважно React, і команда змінюватиметься.
  • Проєкту потрібна екосистема бібліотек, яка сьогодні існує лише для React.
  • Сторінка майже без стану — реактивний механізм стане накладною витратою без застосування.
  • Ніхто не вивчить, де губиться реактивність, — тихі відмови стануть важкими в підтримці.

Було корисно?

Поділіться з тим, хто працює над тією ж задачею.