Kurs Vue.js · Moduł 7: Props i zdarzenia
Walidacja Props
W tej lekcji5
Protokoły komunikacyjne NOVA LAB wymagają walidacji każdego sygnału - Vue oferuje rozbudowany system walidacji props, który chroni komponenty przed nieprawidłowymi danymi.
Sam typ to za mało. Liczba -5 jest poprawną liczbą, a napis 'extreme' poprawnym napisem, a jednak opóźnienie transmisji nie może być ujemne, a priorytetu 'extreme' nie przewiduje żadna procedura stacji. Bywa też gorzej: rodzic zapomina podać nazwę modułu i panel pokazuje pustkę. Walidacja props to kontrola sygnału na wejściu - sprawdza parametry, zanim moduł zacznie z nimi pracować.
Required Props
Domyślnie każdy prop jest opcjonalny. Aby wymusić jego obecność, zamiast samego typu podajesz obiekt z polem type oraz flagą required: true:
1<script setup>
2const props = defineProps({
3 name: {
4 type: String,
5 required: true
6 },
7 // Każdy wymagany prop deklarujesz osobno - nie ma formy skróconej
8 id: {
9 type: Number,
10 required: true
11 }
12})
13</script>Gdy rodzic pominie wymagany prop, Vue wypisze w konsoli ostrzeżenie o brakującym propsie, ale komponent i tak się wyrenderuje, a brakująca wartość będzie po prostu undefined. Walidacja nie blokuje renderowania - ona alarmuje, i to wyłącznie w trybie deweloperskim. W buildzie produkcyjnym Vue pomija te sprawdzenia, żeby nie spowalniać aplikacji.
Domyślne Wartości
Pole default określa wartość, której komponent użyje, gdy rodzic nie poda propsa albo przekaże jawnie undefined. Dla obiektów i tablic wartość domyślną zwraca funkcja fabryczna - dzięki temu każdy egzemplarz komponentu dostaje własną kopię zamiast jednego wspólnego obiektu:
1<script setup>
2const props = defineProps({
3 delay: {
4 type: Number,
5 default: 480 // 8 minut w sekundach
6 },
7 status: {
8 type: String,
9 default: 'standby'
10 },
11 // Dla obiektów i tablic - funkcja fabryczna
12 config: {
13 type: Object,
14 default: () => ({ mode: 'auto', retries: 3 })
15 }
16})
17</script>Zauważ, czego default nie robi: jeśli rodzic przekaże null, wartość domyślna nie zadziała, bo null to świadomie podana wartość, a nie jej brak. Osiem minut to tylko przykładowe opóźnienie łącza - w rzeczywistości sygnał między Ziemią a Marsem biegnie od około 3 do ponad 20 minut.
Wartości domyślne przez destrukturyzację
Od Vue 3.5 wartości domyślne możesz też zapisać przy destrukturyzacji wyniku defineProps. Kompilator pilnuje, żeby tak wyciągnięte zmienne pozostały reaktywne:
1<script setup>
2const { delay = 480, status = 'standby' } = defineProps({
3 delay: Number,
4 status: String
5})
6</script>Działa to tak samo jak pole default: gdy rodzic zmieni delay, zmienna delay w komponencie też się zmieni. W tej lekcji zostaniemy jednak przy polu default, bo w nim cały kontrakt propsa - typ, wymagalność i wartość domyślna - stoi w jednym miejscu.
Custom Validator
Funkcja validator pozwala dopisać własną logikę. Dostaje wartość propsa i zwraca true, gdy wartość jest poprawna, albo false, gdy nie jest:
1<script setup>
2const props = defineProps({
3 delay: {
4 type: Number,
5 default: 480,
6 validator: (value) => {
7 // Delay musi być między 0 a 1440 sekund
8 return value >= 0 && value <= 1440
9 }
10 },
11 priority: {
12 type: String,
13 default: 'normal',
14 validator: (value) => {
15 return ['low', 'normal', 'high', 'critical'].includes(value)
16 }
17 }
18})
19</script>Gdy walidacja nie przejdzie, Vue wyświetli ostrzeżenie w konsoli (w trybie development). Wartość i tak trafi do komponentu, więc walidator traktuj jak lampkę kontrolną, a nie szlaban. Od Vue 3.4 funkcja dostaje drugi argument - obiekt wszystkich propsów - więc może porównać ze sobą dwa parametry. Walidacja odbywa się jeszcze przed utworzeniem instancji komponentu, dlatego ani w validator, ani w default nie sięgniesz do jego stanu.
Wiele Typów
Czasem ten sam kanał przyjmuje sygnały w dwóch formatach, na przykład identyfikator modułu jako liczbę albo tekst. Wtedy zamiast jednego typu podajesz tablicę typów:
1<script setup>
2const props = defineProps({
3 id: [String, Number], // String lub Number
4 value: [String, Number, null] // dozwolony null
5})
6</script>Tablica oznacza "którykolwiek z wymienionych". Typem może być String, Number, Boolean, Array, Object, Date, Function, Symbol, Error albo własna klasa. null w tablicy ma znaczenie przede wszystkim przy propsach wymaganych: opcjonalny prop i tak przepuszcza null bez ostrzeżenia, natomiast wymagany prop z typem [String, null] przyjmie jawne null, a zaalarmuje dopiero przy braku wartości.
Moja rada: wymagaj tylko tego, bez czego moduł traci sens, resztę opatrz rozsądną wartością domyślną, a walidatory pisz dla zakresów i list dozwolonych wartości - tam, gdzie sam typ niczego nie gwarantuje. W edytorze poniżej wpisz opóźnienie większe niż 1440 i zajrzyj do konsoli. Umiesz już bezpiecznie odbierać sygnały z centrali, a w następnej lekcji odwrócimy kierunek: moduł wyśle wiadomość zwrotną przez custom events.
Zapamiętaj: walidacja props to kontrola sygnału na wejściu stacji - ostrzega załogę w laboratorium, ale nie zatrzymuje transmisji.
Kod do tej lekcji: App.vue
1<script setup>
2import { ref } from 'vue'
3import SensorPanel from './SensorPanel.vue'
4
5const sensorDelay = ref(480)
6const sensorName = ref('Czujnik termiczny')
7</script>
8
9<template>
10 <div class="nova-lab">
11 <h1>Walidacja props</h1>
12
13 <label>
14 Opóźnienie (0-1440 s):
15 <input v-model.number="sensorDelay" type="number" />
16 </label>
17 <label>
18 Nazwa:
19 <input v-model="sensorName" />
20 </label>
21
22 <SensorPanel :name="sensorName" :delay="sensorDelay" />
23 <p class="hint">Sprawdź konsolę - walidator wyświetli ostrzeżenie dla delay > 1440</p>
24 </div>
25</template>
26
27<style scoped>
28.nova-lab {
29 background: #0a0e27;
30 color: #00ff88;
31 min-height: 100vh;
32 padding: 20px;
33 font-family: monospace;
34}
35h1 { color: #00ff88; margin-bottom: 20px; }
36label { display: block; margin: 10px 0; color: #00b4d8; }
37input {
38 background: #0a0e27;
39 border: 2px solid #00ff88;
40 color: #00ff88;
41 padding: 8px;
42 margin-left: 10px;
43}
44.hint { color: #ff9900; margin-top: 15px; font-style: italic; }
45</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 oznaczyć prop jako wymagany?
2. Jak ustawić domyślną wartość prop?
To 2 z 3 pytań do tej lekcji. Pozostałe rozwiążesz w grze.
Zadania praktyczne w grze
- Edytor kodu
Dodaj walidację do props: delay musi być między 0 a 1440 sekund, message jest wymagany.
- Układanie w poziomie
Ułóż definicję prop z walidacją:
- Edytor kodu
Stwórz komponent AlarmSystem z Boolean prop 'active' (default: false) i String prop 'level' (default: 'low').