
⚡ Poznajemy podstawy Vue 3: od pustego folderu do komponentów
Patrzy Pan na Vue 3 i widzi Pan fajny frontendowy framework z wielkiej trójki. React, Angular, Vue, brzmi poważnie. A potem otwiera Pan pierwszy poradnik, a tam czekają vite, create-vue i pliki .vue z transpilerami... Tymczasem Vue można podłączyć jednym wierszem <script> i pisać kod od razu. Bez bundlerów, bez JSX, bez piekła konfiguracji.
Dystans między „chcę spróbować" a „napisałem komponent" jest tu krótszy niż gdziekolwiek indziej. Ale większość kursów tego dystansu nie skraca, streszczają dokumentację we fragmentach i nie dają spójnego obrazu. Widzi Pan porozrzucane kawałki składni i nie rozumie Pan, jak zamieniają się w aplikację.
Ten poradnik to dokładnie ta ścieżka, którą sami przeszliśmy z Vue: od pustego folderu do komponentów z propsami. Napisze Pan i uruchomi każdy wiersz samodzielnie. Żadnej magii, tylko działający kod i zrozumienie reaktywności, głównej cechy Vue.
💡 Szybki przegląd:
- Budujemy aplikację Vue na CDN i montujemy w DOM: Pana pierwsza działająca instancja w 5 minut
- Przechodzimy przez cztery kluczowe dyrektywy: v-for, v-if, v-on i v-bind, filary każdego szablonu Vue
- Rozkładamy na części computed i methods: kiedy buforować, a kiedy wywoływać
- Wynosimy logikę do komponentów i przekazujemy dane przez props: krok w stronę prawdziwej architektury
Tworzymy aplikację Vue
Zacznijmy od absolutnego zera. Żadnych create-vue, vite ani vue-cli, po prostu folder z dwoma plikami.
Proszę utworzyć katalog i pliki w terminalu:
1 mkdir vue3-intro 2 cd vue3-intro 3 touch index.html app.js
Albo zrobić to samo przez eksplorator plików. Teraz proszę otworzyć index.html i napisać szkielet:
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>
Trzy kluczowe wiersze. <script src="https://unpkg.com/vue@3/dist/vue.global.js"> podłącza Vue 3 z CDN. To najszybszy sposób startu: biblioteka ładuje się jak zwykły plik JavaScript, niczego nie trzeba budować. <div id="app"> wyznacza punkt montowania, miejsce w DOM, w którym Vue będzie „żyć". Trzeci wiersz importuje app.js, w którym opiszemy logikę.
Teraz wypełnijmy app.js:
1 const app = Vue.createApp({ 2 data() { 3 return { 4 course: 'Введение во Vue 3' 5 } 6 } 7 }) 8 9 app.mount('#app')
Metoda Vue.createApp() tworzy instancję aplikacji. Przekazuje się jej obiekt z ustawieniami, tutaj zadeklarowaliśmy właściwość course przez funkcję data(). Vue czyni każdą właściwość zwróconą z data() reaktywną: przy zmianie wartości DOM zaktualizuje się automatycznie. Żadnych ręcznych manipulacji drzewem.
Ale aplikację trzeba „przypiąć" do elementu na stronie. Robi to app.mount('#app'). Bez tego wiersza Vue nie zareaguje na żadne zmiany, instancja jest utworzona, ale nieuruchomiona.
Pozostało wyświetlić właściwość w HTML. Wewnątrz <div id="app"> proszę napisać:
1 <h1>{{ course }}</h1>
Podwójne nawiasy klamrowe {{ }} to interpolacja, podstawowy sposób wyprowadzania danych w szablonach Vue. Wszystko, co znajduje się wewnątrz {{ }}, Vue zastępuje wartością właściwości z data().

Proszę otworzyć index.html w przeglądarce. Na stronie napis „Wprowadzenie do Vue 3". Pierwsza aplikacja jest gotowa i napisał ją Pan sam, a nie wygenerował przez CLI.
Wyświetlanie list
W prawdziwej aplikacji prawie zawsze pracuje Pan z tablicami: produkty, tagi, posty. Vue daje do tego dyrektywę v-for.
Dodajmy do data() tablicę tagów:
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 })
A w HTML listę:
1 <ul> 2 <li v-for="tag in tags">{{ tag }}</li> 3 </ul>
Dyrektywa v-for iteruje po tablicy tags i dla każdego elementu tworzy własny <li>. Zmienna tag wewnątrz pętli to bieżący element. Wynik wygląda następująco:

Ważny niuans: podczas iterowania po tablicy każdy element DOM potrzebuje unikalnego klucza. Vue używa go, aby śledzić tożsamość węzłów przy aktualizacjach, przyspiesza to przerysowywanie i zapobiega błędom ze stanem.
1 <ul> 2 <li v-for="(tag, index) in tags" :key="index">{{ tag }}</li> 3 </ul>
:key to skrót od v-bind:key, który wiąże atrybut key z wartością indeksu. Jeśli ma Pan tablicę obiektów, na przykład { id: 1, name: 'Vue' }, jako klucz proszę użyć id, a nie indeksu. Indeks zmienia się podczas przestawiania elementów, id jest natomiast stabilne, to bardziej niezawodne rozwiązanie.
Renderowanie warunkowe
Często trzeba pokazać lub ukryć element w zależności od warunku: na przykład przycisk zakupu tylko wtedy, gdy kurs jest dostępny. Vue realizuje to za pomocą dyrektywy v-if.
Dodajmy flagę available w 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 }
I użyjmy jej w znaczniku:
1 <p v-if="available">Курс доступен к покупке!</p> 2 <p v-else>К сожалению, курс сейчас недоступен.</p>
v-if oblicza wyrażenie w cudzysłowie. Jeśli jest prawdziwe, renderowany jest pierwszy blok, w przeciwnym razie v-else. Proszę spróbować w konsoli przeglądarki wykonać app.available = false i zobaczyć, jak strona zareaguje natychmiast.

Oprócz v-if / v-else istnieje jeszcze v-else-if dla łańcuchów warunków oraz v-show. Różnica jest zasadnicza: v-if całkowicie usuwa element z DOM, a v-show jedynie przełącza display: none. Proszę wybierać v-if, gdy warunek zmienia się rzadko. v-show jest odpowiednie do częstych przełączeń, takich jak zakładki, gdzie istotna jest wydajność.
Obsługa zdarzeń
Dyrektywa v-on, w skrócie @, nasłuchuje zdarzeń DOM: kliknięć, wprowadzania danych, najechania kursorem. Gdy zdarzenie nastąpi, Vue uruchamia wskazaną metodę lub wyrażenie.
Dodajmy metodę purchase w konfiguracji aplikacji:
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 })
Sekcja methods zawiera funkcje dostępne w szablonie i innych metodach przez this. Teraz podepnijmy wywołanie do przycisku:
1 <button @click="purchase">Купить</button>

Dla prostych akcji można napisać kod bezpośrednio w @click:
1 <button @click="available = !available">Переключить доступность</button>

Taki kod inline jest wygodny do krótkich operacji, takich jak przełączanie flagi. Jednak złożoną logikę zawsze należy przenosić do metod, szablon musi pozostać czytelny. Zasada jest prosta: counter += 1, OK w szablonie, dziesięć linii logiki zakupu, do metody.
Wiązanie atrybutów
Atrybuty takie jak src, href czy alt często muszą być dynamiczne. Dyrektywa v-bind, w skrócie :, wiąże wartość atrybutu z wyrażeniem z Vue.
Dodajmy dane dla obrazu:
1 data() { 2 return { 3 // ...остальные свойства 4 imgURL: 'https://catalins.tech/img', 5 imgDescription: 'Фотография рабочего стола с компьютером' 6 } 7 }
W szablonie powiążemy je z <img>:
1 <img :src="imgURL" :alt="imgDescription" width="500" height="350">
Pełny zapis wyglądałby tak: v-bind:src="imgURL", dwukropek to po prostu lukier składniowy. Vue śledzi teraz imgURL i imgDescription: proszę je zmienić w data(), a obraz na stronie zaktualizuje się automatycznie. To właśnie reaktywność w działaniu.

Ta sama zasada dotyczy atrybutów takich jak :href, :disabled i :class, a także wszystkich innych. Proszę spróbować samodzielnie: dodać link z dynamicznym href z data() i upewnić się, że działa bez ani jednej zbędnej linii.
Właściwości computed
Czasami dane trzeba przekształcić przed wyświetleniem: sformatować cenę, połączyć imię i nazwisko, sprawdzić warunek. Służą do tego w Vue właściwości computed, czyli obliczane.
Proszę sobie wyobrazić, że chce Pan/Pani zawsze mieć opis obrazu, nawet jeśli pole imgDescription jest puste. Piszemy właściwość computed:
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 })
Teraz w szablonie używamy właściwości computed zamiast surowych danych:
1 <img :src="imgURL" :alt="hasImageDescription" width="500" height="350">
Vue buforuje wynik właściwości computed i przelicza ją tylko wtedy, gdy zmieniają się zależności, w naszym przypadku imgDescription. Jest to wydajniejsze niż wywoływanie funkcji przy każdym renderowaniu.
Ważna zasada: właściwości computed służą do wyświetlania danych, a nie do ich zmiany. Nie należy zmieniać stanu aplikacji wewnątrz computed, od tego są metody.
Metody a właściwości computed
Różnica między methods a computed sprowadza się do jednego pytania: czy zmienia Pan/Pani dane, czy wyświetla wartość pochodną?
Właściwości computed, dla warstwy prezentacji. Formatowanie, filtrowanie, sprawdzanie warunków, łączenie ciągów znaków. Są buforowane i nie mają skutków ubocznych.
Metody, dla akcji. Zmiana wartości w data(), wysłanie żądania, przełączenie checkboxa. Są wywoływane jawnie i mogą robić wszystko.
Typowy antywzorzec: zmienianie this.course wewnątrz computed. Właściwość computed reaguje na zmianę course, ale nie powinna sama go zmieniać. Do zmiany danych zawsze należy użyć metody. Szablon niech opisuje „co pokazać", a nie „jak obliczyć".
Komponenty i props
Kiedy aplikacja się rozrasta, trzymanie wszystkiego w jednym pliku staje się niemożliwe. Vue pozwala podzielić interfejs na komponenty, czyli izolowane bloki z własną logiką, szablonem i stylami.
Stwórzmy pierwszy komponent CourseCard:
1 mkdir components 2 touch components/CourseCard.js
W components/CourseCard.js opiszemy komponent:
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 })
Pierwszy argument app.component(), czyli nazwa, której będziemy używać w HTML jako znacznika: <coursedisplay></coursedisplay>. Drugi, obiekt z data(), computed i template, to „wnętrze" komponentu.
Teraz podłączymy komponent w index.html i użyjemy go:
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>
Zaimportowaliśmy plik komponentu, użyliśmy go jako niestandardowego znacznika i zamontowaliśmy aplikację bezpośrednio w HTML. Logika kursu jest teraz zamknięta wewnątrz CourseCard, a app.js odpowiada wyłącznie za utworzenie instancji.
Props: przekazywanie danych między komponentami
Props, skrót od properties, to mechanizm przekazywania danych z komponentu rodzica do komponentu dziecka. Komponent dziecka deklaruje, jakie props przyjmuje, a rodzic przekazuje je jako atrybuty.
Dodajmy do CourseCard prop paid, który pokazuje, czy kurs jest płatny, czy bezpłatny:
1 app.component('coursedisplay', { 2 props: { 3 paid: { 4 type: Boolean 5 } 6 }, 7 // ...остальная конфигурация 8 })
Komponent rodzica, w naszym przypadku app.js, przekazuje wartość:
1 const app = Vue.createApp({ 2 data() { 3 return { 4 allCourses: 1, 5 paid: true 6 } 7 } 8 })
A w index.html przekazujemy prop:
1 <coursedisplay :paid="paid"></coursedisplay>
Vue automatycznie sprawdza typ przekazanej wartości. Jeśli oczekiwany jest Boolean, a przyszedł string, framework wyświetli ostrzeżenie w konsoli. To ratuje przed głupimi błędami w miarę wzrostu bazy kodu.
Aby prop stał się wymagany, dodaj required: true do jego opisu. Wtedy Vue będzie zgłaszać błąd, jeśli komponent rodzica nie przekaże wartości, i dowie się Pan/Pani o problemie, zanim zepsuje on interfejs.
Pełny kod poradnika znajdzie Pan/Pani w repozytorium vue3-intro na GitHubie, gdzie znajdują się gotowe pliki index.html, app.js i components/CourseCard.js. Proszę zrobić forka i eksperymentować.
Wideo na temat
Aby utrwalić materiał w praktyce, proszę obejrzeć pierwszą lekcję z kursu Vue 3 autorstwa Net Ninja, która doskonale uzupełnia ten poradnik pokazem kodu na żywo:
⁉️🤔 Często zadawane pytania
Czy można używać Vue 3 bez build toola na produkcji?
Tak, podłączenie przez CDN (
unpkg.com/vue@3/dist/vue.global.js) działa również na produkcji. Jednak w przypadku prawdziwych projektów zalecamy przejście na Vite: otrzyma Pan/Pani tree-shaking, code-splitting i Single-File Components, które radykalnie upraszczają rozwój wraz ze wzrostem aplikacji. Szablon startowynpm create vue@latestkonfiguruje to wszystko w minutę.
Czym v-if różni się od v-show?
v-ifcałkowicie usuwa element z DOM, gdy warunek jest fałszywy.v-showpozostawia element w DOM, ale przełącza właściwość CSSdisplay: none. Proszę używaćv-if, gdy warunek zmienia się rzadko, na przykład rola użytkownika.v-showstosuje się przy częstych przełączeniach, takich jak zakładki, gdzie ważna jest szybkość renderowania bez ponownego tworzenia węzłów.
Czy konieczne jest używanie:key w v-for?
Formalnie
v-fordziała bez:key, ale Vue będzie wyświetlać ostrzeżenie w konsoli. Bez klucza framework nie może śledzić, który element DOM odpowiada któremu elementowi danych, co prowadzi do błędów podczas przestawiania i usuwania. Proszę zawsze podawać:keyz unikalnym identyfikatorem,idz danych, a nie indeksem tablicy.
Jaka jest różnica między data() a computed?
data()przechowuje stan początkowy, „surowe" dane.computedwytwarza z nich wartości do wyświetlenia: sformatowany string, przefiltrowaną tablicę, wynik sprawdzenia. Właściwość computed automatycznie aktualizuje się przy zmianie zależności i jest cache’owana między renderowaniami. Metody natomiast są wywoływane za każdym razem od nowa i służą do akcji, a nie do wyświetlania.
Czy można mieszać Options API i Composition API?
Tak, w jednym projekcie można używać obu stylów. Vue 3 w pełni wspiera Options API, a Composition API jest dodatkowym narzędziem do złożonych scenariuszy. Do nauki zalecamy rozpoczęcie od Options API: jest ono bardziej ustrukturyzowane i bliższe mentalnemu modelowi „komponent to obiekt z ustawieniami".
Co robić dalej: Pana/Pani następny krok w Vue 3
Napisał Pan/Pani pierwszą aplikację, rozpracował dyrektywy, właściwości computed i komponenty. To fundament, na którym buduje się dowolne projekty, od landing page’a po panel administracyjny.
Dalej są trzy ścieżki. Pierwsza, utrwalić wiedzę praktyką: proszę wziąć publiczne API, na przykład JSONPlaceholder, i wyświetlić listę postów z filtrowaniem przez computed. Druga, przejść na Vite i pliki .vue: oficjalna dokumentacja Vue 3 przeprowadzi Pana/Panią od create-vue do pierwszego SFC w godzinę. Trzecia, nauczyć się Vue Router i Pinii do budowy pełnoprawnego SPA.
Jeśli chcą Państwo wypróbować Vue całkowicie bez instalacji, proszę zajrzeć do artykułu o podłączaniu Vue przez CDN. Kod startowy z tego poradnika znajduje się w repozytorium vue3-intro, proszę zrobić fork i eksperymentować.



