Skip to content

Wszystko o WordPressie, tworzeniu stron — i nie tylko

⚡ Poznajemy podstawy Vue 3: od pustego folderu do komponentów

⚡ 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:

1mkdir vue3-intro
2cd vue3-intro
3touch 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:

1const app = Vue.createApp({
2 data() {
3 return {
4 course: 'Введение во Vue 3'
5 }
6 }
7})
8
9app.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().

Pierwsza aplikacja Vue 3 w przeglądarce

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:

1const 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:

Lista tagów Vue 3 przez dyrektywę v-for

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():

1data() {
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.

Renderowanie warunkowe w Vue 3 z v-if

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:

1const 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>
Obsługa kliknięcia w Vue 3 przez v-on

Dla prostych akcji można napisać kod bezpośrednio w @click:

1<button @click="available = !available">Переключить доступность</button>
Przełączanie stanu przycisku w Vue 3

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:

1data() {
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.

Wiązanie atrybutów obrazu przez v-bind

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:

1const 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:

1mkdir components
2touch components/CourseCard.js

W components/CourseCard.js opiszemy komponent:

1app.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:

1app.component('coursedisplay', {
2 props: {
3 paid: {
4 type: Boolean
5 }
6 },
7 // ...остальная конфигурация
8})

Komponent rodzica, w naszym przypadku app.js, przekazuje wartość:

1const 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 startowy npm create vue@latest konfiguruje to wszystko w minutę.

Czym v-if różni się od v-show?

v-if całkowicie usuwa element z DOM, gdy warunek jest fałszywy. v-show pozostawia element w DOM, ale przełącza właściwość CSS display: none. Proszę używać v-if, gdy warunek zmienia się rzadko, na przykład rola użytkownika. v-show stosuje 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-for dział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ć :key z unikalnym identyfikatorem, id z danych, a nie indeksem tablicy.

Jaka jest różnica między data() a computed?

data() przechowuje stan początkowy, „surowe" dane. computed wytwarza 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ć.