Kurs Vue.js · Moduł 7: Props i zdarzenia

Walidacja Props

4 min czytania
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. 1. Jak oznaczyć prop jako wymagany?

  2. 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').

Przydatne artykuły