Kurs Vue.js · Moduł 1: Vue i Vite
Narzędzia Diagnostyczne
W tej lekcji5
W kosmosie diagnostyka to kwestia życia i śmierci. Vue DevTools to nasz skaner systemów.
Panel pokazuje zły odczyt i nie wiesz dlaczego: czy winne są dane, szablon, a może komponent w ogóle się nie wyrenderował? Dopisywanie console.log w dziesięciu miejscach to zgadywanie. Potrzebujesz narzędzi, które pokażą wnętrze działającej aplikacji.
Vue DevTools
Vue DevTools to oficjalne narzędzia deweloperskie Vue; wersje od 7 wzwyż obsługują wyłącznie Vue 3. Pierwsza droga instalacji to rozszerzenie przeglądarki:
- Chrome: Vue.js devtools
- Firefox: Vue.js devtools
- Edge: Vue.js devtools
Druga droga to plugin vite-plugin-vue-devtools, który kreator create-vue sam dopisuje do konfiguracji Vite. W trybie deweloperskim panel otwierasz wtedy przyciskiem na dole strony, bez instalowania czegokolwiek w przeglądarce. W projektach z Vite polecam właśnie tę drogę - dokumentacja DevTools zaleca ją ze względu na dodatkowe funkcje.
Funkcje Diagnostyczne
- Component Inspector - skanuj drzewo modułów
- State Inspector - monitoruj dane reaktywne w czasie rzeczywistym
- Timeline - śledź historię zdarzeń i zmian
- Router - debuguj nawigację
- Pinia - zarządzaj bazą danych misji
W obecnych wersjach inspektor komponentów i stanu to jedna zakładka Components: po lewej drzewo, po prawej dane wybranego komponentu, które możesz edytować na żywo. Drzewo typowej aplikacji wygląda tak:
1App
2└── MainLayout (układ: nagłówek, pasek boczny)
3 └── DashboardView (widok)
4 ├── OxygenCard (UI)
5 └── AlertButton (UI)Na szczycie stoi komponent główny, pod nim układ, w układzie widok, a na końcu najmniejsze elementy interfejsu. Kliknij dowolny węzeł, a obok zobaczysz jego dane.
Protokoły Debugowania
Logowanie zmian systemowych
Czasem chcesz zareagować na każdą zmianę, na przykład zapisać ją w konsoli albo podnieść alarm. Służy do tego funkcja watch: pierwszy argument to obserwowane źródło, drugi to funkcja, którą Vue wywoła po każdej zmianie z nową i starą wartością:
1import { ref, watch } from 'vue'
2
3const oxygenLevel = ref(98.5)
4
5// Monitoring zmian
6watch(oxygenLevel, (newLevel, oldLevel) => {
7 console.log(`Poziom tlenu: ${oldLevel}% → ${newLevel}%`)
8
9 if (newLevel < 90) {
10 console.error('ALERT: Niski poziom tlenu!')
11 }
12})Ustaw oxygenLevel.value na 88, a w konsoli pojawi się wpis ze strzałką i czerwony alert. watch niczego nie wyświetla i nie zmienia poziomu tlenu - tylko reaguje. Różnica wobec computed jest prosta: computed wylicza wartość, watch wykonuje akcję.
Debug w template
Druga technika to panel diagnostyczny w szablonie. Dyrektywa v-if wyświetla element tylko wtedy, gdy warunek jest prawdziwy, a JSON.stringify zamienia obiekt z danymi na czytelny tekst:
1<template>
2 <!-- Panel diagnostyczny -->
3 <div v-if="debugMode" class="debug-panel">
4 <pre>{{ JSON.stringify(systemData, null, 2) }}</pre>
5 </div>
6
7 <!-- Wskaźniki krytyczne -->
8 <div class="critical-systems">
9 <span>O2: {{ oxygen }}%</span>
10 <span>Temp: {{ temperature }}°C</span>
11 <span>Ciśnienie: {{ pressure }} hPa</span>
12 </div>
13</template>Gdy debugMode jest fałszem, Vue w ogóle nie tworzy panelu diagnostycznego, a wskaźniki pod nim działają bez zmian. Zmienne użyte w szablonie są zadeklarowane jako ref() w pominiętej tu sekcji <script setup>.
Symulator czujnika
Do testów przyda się pole, w którym wpisujesz odczyt. Dyrektywa v-model wiąże pole z kontenerem w obie strony: wpisana liczba trafia do oxygen, a zmiana oxygen w kodzie trafia do pola. Para v-if i v-else wyświetla jeden z dwóch akapitów:
1<template>
2 <input v-model="oxygen" type="number" />
3 <p v-if="oxygen >= 90">Tlen w normie</p>
4 <p v-else>ALERT: niski poziom tlenu</p>
5</template>
6
7<script setup>
8import { ref } from 'vue'
9
10const oxygen = ref(95)
11</script>Wpisz 85, a komunikat o normie zastąpi alert. v-else musi stać tuż po elemencie z v-if, bo odnosi się do jego warunku. Dyrektywy warunkowe poznasz w Pracowni Hologramów, a formularze z v-model w Symulatorze Sterowania.
Hot Module Replacement
Vite automatycznie aktualizuje moduły bez restartu, a terminal serwera melduje, który plik podmienił:
112:04:31 [vite] (client) hmr update /src/components/LifeSupport.vueFormat godziny zależy od ustawień systemu, a (client) oznacza środowisko przeglądarki. Zmiany są widoczne natychmiast - krytyczne podczas rozwoju systemów!
Komendy Operacyjne
| Komenda | Opis |
|---|---|
npm run dev | Tryb deweloperski (symulator) |
npm run build | Kompilacja do wdrożenia |
npm run preview | Test wersji produkcyjnej |
npm run test:unit | Uruchom testy jednostkowe (Vitest) |
npm run lint | Sprawdź jakość kodu |
To skrypty z package.json, które kreator dopisuje zależnie od wybranych opcji - stąd test:unit zamiast samego test. Typowy cykl pracy: npm run dev, edycja komponentów, odświeżenie przez HMR, a przed wdrożeniem npm run build i sprawdzenie wyniku przez npm run preview.
Przygotowanie do Wdrożenia
Build przebiega w czterech etapach. Vite zaczyna od index.html i znajduje w nim skrypt wejściowy. Potem Rolldown wczytuje kolejne moduły: każdy najpierw przechodzi transformację (pliki .vue kompiluje plugin Vue, a TypeScript i JSX zamienia na JavaScript narzędzie Oxc), a dopiero potem Rolldown odczytuje z niego importy i sięga po następne pliki, budując graf zależności. Następnie Rolldown skleja moduły w paczki, usuwa nieużywany kod i minifikuje wynik, a na końcu pliki trafiają do katalogu dist. Do wersji 7 transformację wykonywał esbuild, a paczki sklejał Rollup.
1# Kompilacja systemu
2npm run build
3
4# Wynik w katalogu /dist
5dist/
6├── index.html
7├── assets/
8│ ├── index-[hash].js # Skompilowana logika
9│ └── index-[hash].css # Skompilowane style[hash] to skrót zawartości pliku: po zmianie kodu zmienia się nazwa, więc przeglądarka nie użyje starej wersji z pamięci podręcznej. npm run preview serwuje ten katalog lokalnie, ale nie jest serwerem produkcyjnym - wdrożeniem zajmiemy się na Platformie Startowej.
Ten kod poleci na Marsa. Każdy błąd może kosztować życie załogi. Testuj dokładnie! W edytorze poniżej zmieniaj licznik, wpisuj komunikat i przełączaj system, obserwując te same zmiany w DevTools.
Zapamiętaj: DevTools pokazuje wnętrze systemu, watch reaguje na każdą zmianę, a npm run build pakuje sprawdzony kod do katalogu dist.
Kod do tej lekcji: src/App.vue
1<template>
2 <div class="nova-lab">
3 <h1>Vue DevTools</h1>
4
5 <section class="info">
6 <h2>Twój najlepszy przyjaciel podczas developmentu</h2>
7 <p>
8 Vue DevTools to rozszerzenie przeglądarki, które pozwala:
9 </p>
10 <ul>
11 <li>Przeglądać drzewo komponentów</li>
12 <li>Sprawdzać i edytować stan (state)</li>
13 <li>Śledzić zdarzenia (events)</li>
14 <li>Debugować Pinia stores</li>
15 <li>Analizować wydajność</li>
16 </ul>
17 </section>
18
19 <section class="demo">
20 <h2>Interaktywny Stan</h2>
21 <p>Otwórz DevTools i obserwuj jak zmienia się stan:</p>
22
23 <div class="state-demo">
24 <div class="counter">
25 <button @click="count--">-</button>
26 <span>{{ count }}</span>
27 <button @click="count++">+</button>
28 </div>
29
30 <div class="input-demo">
31 <input v-model="message" placeholder="Wpisz wiadomość..." />
32 <p>{{ message }}</p>
33 </div>
34
35 <div class="toggle-demo">
36 <label>
37 <input type="checkbox" v-model="isActive" />
38 System aktywny
39 </label>
40 <div class="status" :class="{ active: isActive }">
41 {{ isActive ? 'ONLINE' : 'OFFLINE' }}
42 </div>
43 </div>
44 </div>
45 </section>
46
47 <section class="install">
48 <h2>Instalacja</h2>
49 <div class="browser-links">
50 <a href="https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd" target="_blank" class="browser-btn">
51 Chrome
52 </a>
53 <a href="https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/" target="_blank" class="browser-btn">
54 Firefox
55 </a>
56 <a href="https://microsoftedge.microsoft.com/addons/detail/vuejs-devtools/olofadcdnkkjdfgjcmjaadnlehnnihnl" target="_blank" class="browser-btn">
57 Edge
58 </a>
59 </div>
60 </section>
61 </div>
62</template>
63
64<script setup>
65import { ref } from 'vue'
66
67const count = ref(0)
68const message = ref('')
69const isActive = ref(true)
70</script>
71
72<style>
73.nova-lab {
74 min-height: 100vh;
75 background: #0a0e27;
76 color: #e0e0e0;
77 padding: 2rem;
78 font-family: system-ui, sans-serif;
79}
80
81h1 {
82 color: #00ff88;
83 text-align: center;
84}
85
86section {
87 background: rgba(26, 30, 55, 0.8);
88 border: 1px solid #00b4d8;
89 border-radius: 12px;
90 padding: 1.5rem;
91 margin: 1.5rem auto;
92 max-width: 600px;
93}
94
95h2 {
96 color: #00b4d8;
97 margin-top: 0;
98}
99
100ul {
101 list-style: none;
102 padding: 0;
103}
104
105ul li {
106 padding: 0.5rem 0;
107 border-bottom: 1px solid rgba(0, 180, 216, 0.2);
108}
109
110ul li::before {
111 content: "» ";
112 color: #00ff88;
113}
114
115.state-demo {
116 display: flex;
117 flex-direction: column;
118 gap: 1rem;
119}
120
121.counter {
122 display: flex;
123 align-items: center;
124 justify-content: center;
125 gap: 1rem;
126}
127
128.counter button {
129 width: 40px;
130 height: 40px;
131 background: #00b4d8;
132 color: #0a0e27;
133 border: none;
134 border-radius: 8px;
135 font-size: 1.25rem;
136 cursor: pointer;
137}
138
139.counter span {
140 font-size: 1.5rem;
141 font-weight: bold;
142 color: #00ff88;
143 min-width: 60px;
144 text-align: center;
145}
146
147.input-demo input {
148 width: 100%;
149 padding: 0.75rem;
150 background: #1a1e37;
151 border: 2px solid #00b4d8;
152 border-radius: 8px;
153 color: #fff;
154}
155
156.input-demo p {
157 color: #00ff88;
158 font-style: italic;
159 min-height: 1.5rem;
160}
161
162.toggle-demo {
163 display: flex;
164 align-items: center;
165 justify-content: space-between;
166}
167
168.toggle-demo label {
169 display: flex;
170 align-items: center;
171 gap: 0.5rem;
172 cursor: pointer;
173}
174
175.status {
176 padding: 0.5rem 1rem;
177 border-radius: 20px;
178 font-weight: bold;
179 background: rgba(255, 68, 68, 0.2);
180 color: #ff4444;
181}
182
183.status.active {
184 background: rgba(0, 255, 136, 0.2);
185 color: #00ff88;
186}
187
188.browser-links {
189 display: flex;
190 gap: 1rem;
191 justify-content: center;
192 flex-wrap: wrap;
193}
194
195.browser-btn {
196 padding: 0.75rem 1.5rem;
197 background: #1a1e37;
198 border: 2px solid #00b4d8;
199 border-radius: 8px;
200 color: #00b4d8;
201 text-decoration: none;
202 transition: all 0.2s;
203}
204
205.browser-btn:hover {
206 background: #00b4d8;
207 color: #0a0e27;
208}
209</style>Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Jak nazywają się oficjalne narzędzia deweloperskie dla Vue.js?
2. Jaka komenda kompiluje projekt Vue/Vite do wersji produkcyjnej?
3. Do czego służy funkcja watch() w Vue 3?
4. Kto jest twórcą zarówno Vue.js jak i Vite?
Zadania praktyczne w grze
- Układanie w pionie
Ułóż proces instalacji i uruchomienia projektu Vue.js od zera:
- Edytor kodu
Uzupełnij komponent z watch() monitorującym zmiany zmiennej reaktywnej i logującym je w konsoli.
- Klikanie w kolejności
Ułóż składnię funkcji watch w Vue 3:
- Układanie w pionie
Ułóż typowy workflow pracy z Vite od developmentu do produkcji:
- Układanie w poziomie
Ułóż składnię warunkowego renderowania elementu:
- Edytor kodu
Użyj v-if i v-else do warunkowego wyświetlania statusu systemu w zależności od wartości zmiennej.
- Układanie w pionie
Ułóż strukturę projektu Vue od pliku wejściowego do komponentu:
- Układanie w poziomie
Ułóż składnię przycisku z obsługą zdarzenia click w Vue:
- Klikanie w kolejności
Ułóż poprawny import funkcji ref z Vue:
- Układanie w pionie
Ułóż kolejność operacji w pliku main.js:
- Układanie w poziomie
Ułóż składnię dynamicznego bindowania klasy CSS w Vue:
- Klikanie w kolejności
Ułóż składnię computed property w Vue 3:
- Układanie w pionie
Ułóż etapy procesu build w Vite od kodu źródłowego do produkcji:
- Klikanie w kolejności
Ułóż poprawną sekcję style z atrybutem scoped:
- Układanie w poziomie
Ułóż składnię inputa z dwukierunkowym bindowaniem danych w Vue:
- Układanie w pionie
Ułóż hierarchię komponentów od najwyższego do najniższego poziomu: