
⚡ Вивчаємо основи Vue 3: від порожньої папки до компонентів
Ви дивитеся на Vue 3 і бачите крутий фронтенд-фреймворк із великої трійки. React, Angular, Vue, звучить серйозно. А потім відкриваєте перший посібник, а там чекають vite, create-vue і .vue-файли з транспайлерами... Хоча насправді Vue можна підключити одним рядком <script> і писати код просто зараз. Без збирачів, без JSX, без пекла налаштувань.
Розрив між «хочу спробувати» і «я написав компонент» тут коротший, ніж будь-де. Але більшість уроків цей розрив не скорочують, вони переказують документацію фрагментами й не дають цілісної картини. Ви бачите розрізнені шматки синтаксису й не розумієте, як вони перетворюються на застосунок.
Цей посібник — це саме той шлях, який ми самі пройшли з Vue: від порожньої теки до компонентів із props. Ви напишете й запустите кожен рядок самостійно. Жодної магії, лише робочий код і розуміння реактивності, головної фішки Vue.
💡 Швидкий огляд:
- Збираємо застосунок Vue на CDN і монтуємо в DOM: ваш перший робочий екземпляр за 5 хвилин
- Проходимо чотири ключові директиви, v-for, v-if, v-on і v-bind: стовпи будь-якого Vue-шаблону
- Розбираємо computed і methods: коли кешувати, а коли викликати
- Виносимо логіку в компоненти й прокидаємо дані через props: крок до реальної архітектури
Створюємо застосунок Vue
Почнімо з абсолютного нуля. Жодних create-vue, vite або vue-cli, просто тека з двома файлами.
Створіть директорію та файли в терміналі:
1 mkdir vue3-intro 2 cd vue3-intro 3 touch index.html app.js
Або зробіть те саме через провідник. Тепер відкрийте index.html і напишіть каркас:
1 <!DOCTYPE html> 2 <html lang="ru"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> 7 <title>Vue 3 — первые шаги</title> 8 </head> 9 <body> 10 <div id="app"></div> 11 <script src="./app.js"></script> 12 </body> 13 </html>
Три ключові рядки. <script src="https://unpkg.com/vue@3/dist/vue.global.js"> підключає Vue 3 із CDN. Це найшвидший спосіб старту: бібліотека завантажується як звичайний JavaScript-файл, нічого збирати не потрібно. <div id="app"> задає точку монтування: місце в DOM, де Vue «житиме». Третій рядок імпортує app.js, у якому ми опишемо логіку.
Тепер наповнімо app.js:
1 const app = Vue.createApp({ 2 data() { 3 return { 4 course: 'Введение во Vue 3' 5 } 6 } 7 }) 8 9 app.mount('#app')
Метод Vue.createApp() створює екземпляр застосунку. Йому передається об'єкт із налаштуваннями, тут ми оголосили властивість course через функцію data(). Vue робить кожну повернену з data() властивість реактивною: при зміні значення DOM оновиться автоматично. Жодних ручних маніпуляцій із деревом.
Але застосунок потрібно «прикріпити» до елемента на сторінці. Це робить app.mount('#app'). Без цього рядка Vue не реагуватиме на жодні зміни, екземпляр створено, але не запущено.
Залишилося відобразити властивість у HTML. Всередині <div id="app"> напишіть:
1 <h1>{{ course }}</h1>
Подвійні фігурні дужки {{ }} — це інтерполяція, основний спосіб виведення даних у шаблонах Vue. Усе, що всередині {{ }}, Vue замінює значенням властивості з data().

Відкрийте index.html у браузері. На сторінці напис «Вступ до Vue 3». Перший застосунок готовий, і ви написали його самі, а не згенерували через CLI.
Відображення списків
У реальному застосунку ви майже завжди працюєте з масивами: товари, теги, пости. Vue дає для цього директиву v-for.
Додаймо в data() масив тегів:
1 const app = Vue.createApp({ 2 data() { 3 return { 4 course: 'Введение во Vue 3', 5 description: 'Базовое руководство по Vue 3 для новичков', 6 price: '$19.99', 7 tags: ['Vue', 'Frontend', 'JavaScript'] 8 } 9 } 10 })
А в HTML, список:
1 <ul> 2 <li v-for="tag in tags">{{ tag }}</li> 3 </ul>
Директива v-for перебирає масив tags і для кожного елемента створює свій <li>. Змінна tag усередині циклу — це поточний елемент. Результат має такий вигляд:

Важливий нюанс: під час обходу масиву кожному елементу DOM потрібен унікальний ключ. Vue використовує його, щоб відстежувати ідентичність вузлів при оновленнях — це пришвидшує перемальовування й запобігає багам зі станом.
1 <ul> 2 <li v-for="(tag, index) in tags" :key="index">{{ tag }}</li> 3 </ul>
:key — це скорочення для v-bind:key, яке прив’язує атрибут key до значення індексу. Якщо у вас масив об’єктів, наприклад { id: 1, name: 'Vue' }, як ключ беріть id, а не індекс. Індекс змінюється під час перестановок, id же стабільний — це надійніше.
Умовний рендеринг
Часто потрібно показати або приховати елемент залежно від умови: кнопку купівлі, лише якщо курс доступний. Vue робить це директивою v-if.
Додамо прапорець available у data():
1 data() { 2 return { 3 course: 'Введение во Vue 3', 4 description: 'Базовое руководство по Vue 3 для новичков', 5 price: '$19.99', 6 available: true, 7 tags: [ 8 { id: 1, name: 'Vue' }, 9 { id: 2, name: 'Frontend' }, 10 { id: 3, name: 'JavaScript' } 11 ] 12 } 13 }
І використаємо в розмітці:
1 <p v-if="available">Курс доступен к покупке!</p> 2 <p v-else>К сожалению, курс сейчас недоступен.</p>
v-if обчислює вираз у лапках. Якщо він істинний, рендериться перший блок, інакше, v-else. Спробуйте в консолі браузера виконати app.available = false і подивіться, як сторінка відреагує миттєво.

Крім v-if / v-else є ще v-else-if для ланцюжків умов і v-show. Різниця принципова: v-if повністю видаляє елемент із DOM, а v-show лише перемикає display: none. Обирайте v-if, коли умова змінюється рідко. v-show, для частих перемикань, як-от таби, де важлива продуктивність.
Обробка подій
Директива v-on, простіше @, слухає DOM-події: кліки, введення, наведення. Подія сталася, Vue запускає вказаний метод або вираз.
Додамо метод purchase у налаштування застосунку:
1 const app = Vue.createApp({ 2 data() { 3 return { 4 course: 'Введение во Vue 3', 5 description: 'Базовое руководство по Vue 3 для новичков', 6 price: '$19.99', 7 available: true, 8 tags: [ 9 { id: 1, name: 'Vue' }, 10 { id: 2, name: 'Frontend' }, 11 { id: 3, name: 'JavaScript' } 12 ] 13 } 14 }, 15 methods: { 16 purchase() { 17 console.log('Курс куплен!') 18 } 19 } 20 })
Секція methods містить функції, доступні в шаблоні та інших методах через this. Тепер повісимо виклик на кнопку:
1 <button @click="purchase">Купить</button>

Для простих дій можна писати код прямо в @click:
1 <button @click="available = !available">Переключить доступность</button>

Такий інлайн-код зручний для коротких операцій на кшталт перемикання прапорця. Але складну логіку завжди виносьте в методи, шаблон має залишатися читабельним. Правило просте: counter += 1, ок у шаблоні, десять рядків логіки купівлі, у метод.
Прив’язка атрибутів
Атрибути на кшталт src, href або alt часто мають бути динамічними. Директива v-bind, скорочено :, пов’язує значення атрибута з виразом із Vue.
Додамо дані для зображення:
1 data() { 2 return { 3 // ...остальные свойства 4 imgURL: 'https://catalins.tech/img', 5 imgDescription: 'Фотография рабочего стола с компьютером' 6 } 7 }
У шаблоні прив’яжемо їх до <img>:
1 <img :src="imgURL" :alt="imgDescription" width="500" height="350">
Розгорнутий запис мав би вигляд v-bind:src="imgURL", двокрапка — це просто синтаксичний цукор. Vue тепер відстежує imgURL та imgDescription: змініть їх у data(), і зображення на сторінці оновиться автоматично. Це і є реактивність у дії.

Той самий принцип застосовний до атрибутів на кшталт :href, :disabled і :class, а також до будь-яких інших. Спробуйте самі: додайте посилання з динамічним href із data() і переконайтеся, що працює без жодного зайвого рядка.
Обчислювані властивості
Іноді дані потрібно перетворити перед показом: відформатувати ціну, склеїти ім’я та прізвище, перевірити умову. Для цього у Vue є computed, обчислювані властивості.
Уявіть, що ви хочете завжди мати опис зображення, навіть якщо поле imgDescription порожнє. Пишемо обчислювану властивість:
1 const app = Vue.createApp({ 2 data() { 3 return { 4 course: 'Введение во Vue 3', 5 description: 'Базовое руководство по Vue 3 для новичков', 6 price: '$19.99', 7 available: true, 8 imgURL: 'https://catalins.tech/img', 9 imgDescription: 'Фотография рабочего стола с компьютером', 10 tags: [ 11 { id: 1, name: 'Vue' }, 12 { id: 2, name: 'Frontend' }, 13 { id: 3, name: 'JavaScript' } 14 ] 15 } 16 }, 17 computed: { 18 hasImageDescription() { 19 return this.imgDescription.length > 0 20 ? this.imgDescription 21 : 'Автоматическое описание изображения' 22 } 23 } 24 })
Тепер у шаблоні використовуємо обчислювану властивість замість сирих даних:
1 <img :src="imgURL" :alt="hasImageDescription" width="500" height="350">
Vue кешує результат computed-властивості й перераховує її лише тоді, коли змінюються залежності, у нашому випадку, imgDescription. Це ефективніше, ніж викликати функцію під час кожного рендеру.
Важливе правило: обчислювані властивості призначені для відображення даних, а не для їх зміни. Не змінюйте стан застосунку всередині computed, для цього є методи.
Методи проти обчислюваних властивостей
Різниця між methods і computed зводиться до одного питання: ви змінюєте дані чи відображаєте похідне значення?
Обчислювані властивості, для рівня представлення. Форматування, фільтрація, перевірка умов, склеювання рядків. Вони кешуються і не мають побічних ефектів.
Методи, для дій. Змінити значення в data(), надіслати запит, перемкнути прапорець. Вони викликаються явно і можуть робити що завгодно.
Типовий антипатерн, змінювати this.course всередині computed. Обчислювана властивість реагує на зміну course, але не повинна змінювати його сама. Для зміни даних завжди беріть метод. Шаблон нехай описує «що показувати», а не «як обчислювати».
Компоненти та props
Коли застосунок розростається, тримати все в одному файлі стає неможливо. Vue дозволяє розбити інтерфейс на компоненти, ізольовані блоки зі своєю логікою, шаблоном і стилями.
Створимо перший компонент CourseCard:
1 mkdir components 2 touch components/CourseCard.js
У components/CourseCard.js опишемо компонент:
1 app.component('coursedisplay', { 2 data() { 3 return { 4 course: 'Введение во Vue 3', 5 description: 'Базовое руководство по Vue 3 для новичков', 6 price: '$19.99', 7 available: true, 8 imgURL: 'https://catalins.tech/img', 9 imgDescription: 'Фотография рабочего стола с компьютером', 10 tags: [ 11 { id: 1, name: 'Vue' }, 12 { id: 2, name: 'Frontend' }, 13 { id: 3, name: 'JavaScript' } 14 ] 15 } 16 }, 17 computed: { 18 hasImageDescription() { 19 return this.imgDescription.length > 0 20 ? this.imgDescription 21 : 'Автоматическое описание изображения' 22 } 23 }, 24 template: ` 25 <img :src="imgURL" :alt="hasImageDescription" width="500" height="350"> 26 <h1>{{ course }}</h1> 27 <p>{{ description }}</p> 28 <p>{{ price }}</p> 29 <button @click="available = !available">Купить</button> 30 <ul> 31 <li v-for="tag in tags" :key="tag.id">{{ tag.name }}</li> 32 </ul> 33 <p v-if="available">Курс доступен к покупке!</p> 34 <p v-else>К сожалению, курс сейчас недоступен.</p> 35 ` 36 })
Перший аргумент app.component(), ім’я, яке ми використовуватимемо в HTML як тег: <coursedisplay></coursedisplay>. Другий, об’єкт із data(), computed і template, це «начинка» компонента.
Тепер підключимо компонент в index.html і використаємо його:
1 <div id="app"> 2 <coursedisplay></coursedisplay> 3 </div> 4 <script src="./app.js"></script> 5 <script src="./components/CourseCard.js"></script> 6 <script> 7 const mountedApp = app.mount('#app') 8 </script>
Ми імпортували файл компонента, використали його як користувацький тег і змонтували застосунок прямо в HTML. Логіка курсу тепер замкнена всередині CourseCard, а app.js відповідає лише за створення екземпляра.
Props: передавання даних між компонентами
Props, скорочення від properties — це механізм передавання даних від батьківського компонента до дочірнього. Дочірній компонент оголошує, які props він приймає, а батьківський передає їх як атрибути.
Додамо до CourseCard prop paid, який показує, платний курс чи безплатний:
1 app.component('coursedisplay', { 2 props: { 3 paid: { 4 type: Boolean 5 } 6 }, 7 // ...остальная конфигурация 8 })
Батьківський компонент, у нашому випадку app.js, передає значення:
1 const app = Vue.createApp({ 2 data() { 3 return { 4 allCourses: 1, 5 paid: true 6 } 7 } 8 })
І в index.html прокидаємо prop:
1 <coursedisplay :paid="paid"></coursedisplay>
Vue автоматично перевіряє тип переданого значення. Якщо очікується Boolean, а прийшов рядок, фреймворк видасть попередження в консолі. Це рятує від дурних помилок зі зростанням кодової бази.
Щоб prop став обов’язковим, додайте required: true до його опису. Тоді Vue сваритиметься, якщо батьківський компонент не передав значення, і ви дізнаєтеся про проблему до того, як вона зламає інтерфейс.
Повний код посібника ви знайдете в репозиторії vue3-intro на GitHub, там лежать готові файли index.html, app.js і components/CourseCard.js. Форкніть і експериментуйте.
Відео за темою
Щоб закріпити матеріал на практиці, подивіться перший урок із курсу Net Ninja з Vue 3, він чудово доповнює цей посібник живим показом коду:
⁉️🤔 Часті запитання
Чи можна використовувати Vue 3 без збирача в продакшені?
Так, підключення через CDN (
unpkg.com/vue@3/dist/vue.global.js) працює і в продакшені. Але для реальних проєктів ми рекомендуємо перейти на Vite: ви отримаєте tree-shaking, code-splitting і Single-File Components, які різко спрощують розробку зі зростанням застосунку. Стартовий шаблонnpm create vue@latestзбирає все це за хвилину.
Чим v-if відрізняється від v-show?
v-ifповністю видаляє елемент із DOM, коли умова хибна.v-showзалишає елемент у DOM, але перемикає CSS-властивістьdisplay: none. Використовуйтеv-if, коли умова змінюється рідко, наприклад, роль користувача.v-show, для частих перемикань, як-от таби, де важлива швидкість рендерингу без перестворення вузлів.
Чи обов’язково використовувати:key у v-for?
Формально
v-forпрацює без:key, але Vue видаватиме попередження в консолі. Без ключа фреймворк не може відстежити, який елемент DOM відповідає якому елементу даних — це призводить до багів під час перестановок і видалення. Завжди вказуйте:keyз унікальним ідентифікатором,idіз даних, а не індекс масиву.
У чому різниця між data() і computed?
data()зберігає початковий стан, «сирі» дані.computedвиробляє з них значення для відображення: форматований рядок, відфільтрований масив, результат перевірки. Обчислювана властивість автоматично оновлюється зі зміною залежностей і кешується між рендерами. Методи ж викликаються щоразу заново і призначені для дій, а не для відображення.
Чи можна змішувати Options API і Composition API?
Так, в одному проєкті можна використовувати обидва стилі. Vue 3 підтримує Options API повністю, а Composition API — це додатковий інструмент для складних сценаріїв. Для навчання ми рекомендуємо почати з Options API: він структурованіший і ближчий до ментальної моделі «компонент — це об’єкт із налаштуваннями».
Що робити далі: ваш наступний крок у Vue 3
Ви написали перший застосунок, розібрали директиви, обчислювані властивості та компоненти. Це фундамент, на якому будуються будь-які проєкти, від лендингу до панелі адміністратора.
Далі три шляхи. Перший, закріпити практикою: візьміть публічне API, наприклад JSONPlaceholder, і відобразіть список постів із фільтрацією через computed. Другий, перейти на Vite і .vue-файли: офіційна документація Vue 3 проведе вас від create-vue до першого SFC за годину. Третій, вивчити Vue Router і Pinia для побудови повноцінного SPA.
Якщо хочете спробувати Vue взагалі без встановлення, зазирніть у статтю про підключення Vue через CDN. А стартовий код із цього посібника лежить у репозиторії vue3-intro, форкніть і експериментуйте.



