Lekce 4 - Podmínky a cykly ve Vue
V minulé lekci, Data a props v komponentách ve Vue, jsme se naučili pracovat s daty uvnitř Vue komponenty a předávat data do jednotlivých komponent prostřednictvím props. Také jsme se seznámili s možností validovat props a mít tak pod kontrolou datové typy.
V této lekci Vue tutoriálu budeme pokračovat v tvorbě kalkulačky. Podíváme se blíže na podmínky a cykly. Připomeňme si nejdříve finální vzhled, kterého s naší kalkulačkou chceme dosáhnout.
Renderování v cyklech
V tuto chvíli máme hotový první řádek, zbývají nám tedy čtyři řádky:
Všimněme si, co mají společného - všechny obsahují právě čtyři
tlačítka. V komponentě TheLayout
jsme tyto řádky prozatím
nahradili obyčejným elementem <div>
. Je na čase vytvořit
si komponentu, která nám bude reprezentovat právě jeden takový řádek se
čtyřmi kalkulačkovými tlačítky.
V adresáři src/components
vytvoříme nový soubor s názvem
CalculatorRow.vue
a napíšeme do něj tento kód:
<template> <div class="calculator-row"> <calculator-button v-for="button of buttons" :key="button" :display-value="button"/> </div> </template> <script> export default { name: 'CalculatorRow', props: { buttons: { required: true, validator: (v) => Array.isArray(v) && v.length === 4 && new Set(v).size === 4 } }, } </script>
Nejprve si vysvětleme props ve skriptu. Komponenta bude
požadovat povinnou prop s názvem buttons
. Ve validační funkci
ověříme, že hodnota má datový typ pole. Dále ověříme, že toto pole
obsahuje právě čtyři prvky. Nakonec ověříme skutečnost, že všechny
prvky v poli mají unikátní hodnotu (v řádku se nemohou opakovat dvě
stejná tlačítka). Touto validační funkcí navazujeme na předchozí lekci a
připomínáme si užití validace props v komponentách.
Druhý řádek kalkulačky bude obsahovat tlačítka 7
,
8
, 9
a /
. Komponenta
CalculatorRow
, která bude tento řádek představovat, bude proto
muset dostat do své prop buttons
toto pole:
['7', '8', '9', '/']
.
Pokud pole validační kritéria nesplní, například bude obsahovat 2x
tlačítko 7: ['7', '7', '9', '/']
, objeví se po spuštění
stránky v konzoli prohlížeče varování:
Nyní k šabloně. Ta je tvořena obalujícím elementem
<div>
s CSS třídou .calculator-row
. Tato
třída je již deklarována ve stylech komponenty TheLayout
a
není tedy třeba ji znovu deklarovat zde. CSS deklarace jsou ve Vue
globální, pokud toto nastavení nezměníme, ale o tom později.
Obalový element <div>
obsahuje komponentu
CalculatorButton
. Připomeňme si, že jsme ji registrovali v
druhé lekci globálně, o její registraci se tedy v tuto chvíli už starat
nemusíme.
V zápisu této komponenty v šabloně si všimněme direktivy
v-for
. Jde o direktivu, která nám umožňuje cyklické
renderování podle prvků pole. Kód v-for="button of buttons"
prochází pole buttons
, které máme definované v props.
Při každé této iteraci se vytvoří jedna instance
komponenty CalculatorButton
. Tímto kódem jsme si též
vytvořili proměnnou button
, která obsahuje právě iterovaný
prvek pole buttons
. Proměnou používáme hned v téže
komponentě. Pomocí direktivy v-bind
přiřazujeme hodnotu
proměnné button
do prop s názvem displayValue
komponenty CalculatorButton
. Do tlačítka tak dostáváme právě
ten znak, který na něm má být zobrazen.
Dále si všimněme direktivy v-key
, která je v kódu zapsána
zkratkou :key
(oba zápisy v-key
a :key
jsou ekvivalentní). Při renderování v cyklech je třeba,
aby každá zobrazovaná komponenta měla k sobě přiřazen unikátní klíč,
pomocí kterého ji Vue bude moci identifikovat. Toto přiřazení klíče je
syntaktickou podmínkou frameworku Vue 3. V naší kalkulačce
si můžeme být jisti, že každé tlačítko bude obsahovat jiný znak.
Hodnota proměnné button
tedy bude jedinečná a můžeme ji
přímo použít jako klíč.
Podrobněji o direktivě
v-for
Následující příklady s naší kalkulačkou přímo nesouvisí, můžete si je ale vyzkoušet v kterékoliv již existující zobrazované komponentě, případně si pro ně vytvořit komponentu novou.
Renderování cyklů můžeme použít na kterékoliv Vue komponentě, stejně tak ale i na libovolném HTML elementu. Například kód:
<template> <div v-for="greeting of ['ahoj', 'čau']" :key="greeting" >{{ greeting }}</div> </template>
nám zobrazí dva elementy <div>
, první s textem "ahoj",
druhý s textem "čau".
Pro úplnost ještě dodejme, že kromě právě iterovaného prvku pole můžeme zobrazované komponentě (anebo HTML elementu) předat také index (pořadí prvku v poli počítané od nuly).
Předchozí kód nyní upravíme takto:
<template> <div v-for="(greeting, index) of ['ahoj', 'čau']" :key="greeting" >{{ (index + 1) + '. pozdrav:' + greeting }}</div> </template>
Tím se zobrazí dva elementy <div>
, které budou
obsahovat texty "1. pozdrav: ahoj" a "2. pozdrav: čau".
Vnoření cyklů
Vraťme se zpět k naší kalkulačce. Máme vytvořenou komponentu
CalculatorRow
, zatím ji však nikde nezobrazujeme. Zobrazíme ji v
naší hlavní komponentě TheLayout
a to dokonce čtyřikrát,
protože naše kalkulačka bude mít celkem čtyři řádky. Upravíme si skript
komponenty TheLayout
takto:
import CalculatorRow from '@/components/CalculatorRow.vue' export default { name: 'TheLayout', data () { return { value: '0', rows: [ ['7', '8', '9', '/'], ['4', '5', '6', 'X'], ['1', '2', '3', '-'], ['0', ',', '=', '+'] ] } }, components: { CalculatorRow } }
Tím jsme v datech této komponenty vytvořili dvourozměrné pole
rows
. Jeho prvky jsou pole obsahující znaky tlačítek na
jednotlivých řádcích kalkulačky. Nyní už nám nic nebrání použít
komponentu CalculatorRow
v cyklu. Šablonu TheLayout
tedy upravíme takto:
<template> <div class="container"> <div class="calculator"> <div class="calculator-row"> <div class="display"></div> <calculator-button display-value="C"/> </div> <calculator-row v-for="(row, index) of rows" :key="'row' + (index + 1)" :buttons="row"/> </div> </div> </template>
Nyní vidíme, že jsme pod prvním řádkem kalkulačky zobrazili čtyři
další řádky, a to cyklickým použitím komponenty
CalculatorRow
. Ta sama již v sobě obsahuje cyklus pro
zobrazování jednotlivých tlačítek, náš kód je tedy příkladem toho, jak
je možné zobrazovat cykly navzájem vnořené do sebe.
Podobně by mohlo být nakódováno vnoření dvou cyklů jen v jediné
komponentě, protože direktiva v-for
může být neomezeně
zanořována. Všimněme si také, že pole znaků, které mají být zobrazeny
v jednotlivých řádcích kalkulačky, předáváme direktivou
v-bind
do prop buttons
každé instance komponenty
CalculatorRow
.
Unikátní klíč každé instance této komponenty nyní tvoříme pomocí stringu "row" a indexu. Klíče budou mít hodnoty "row1", "row2", atd., čímž je zajištěna jejich jedinečnost v celém HTML dokumentu.
V prohlížeči nyní uvidíme kalkulačku v této podobě:
Podmíněné
renderování - direktivy v-if
, v-else-if
,
v-else
Direktiva v-if
musí obsahovat JavaScriptový výraz a
komponenta, resp. HTML element direktivu obsahující, se zobrazí jen tehdy,
je-li výsledek výrazu pravdivý (truthy).
Podobně funguje direktiva v-else-if
, musí však být řazena v
pořadí za v-if
a její výraz se vyhodnocuje pouze tehdy,
není-li splněna podmínka předchozí v-if
.
Direktiva v-else
již žádný výraz neobsahuje a musí být
řazena za direktivu v-if
, respektive v-else-if
.
Element, který ji obsahuje, je zobrazen pouze tehdy, není-li splněna žádná
z podmínek předchozích direktiv.
Je třeba připomenout, že zobrazovaní elementů pomocí těchto direktiv
je absolutní, nejde tedy o pouhé skrývání či odkrývání
elementů pomocí CSS stylů (např. display: none
nebo
visibility: hidden
). Elementy, u kterých tyto direktivy určí,
že nemají být zobrazeny, zkrátka nejsou ve výsledném HTML
dokumentu vůbec obsaženy.
Abychom si vyzkoušeli podmíněné renderování, odlišíme graficky
pozadí tlačítka, které obsahuje písmeno "C", od ostatních tlačítek
kalkulačky. Upravme proto kód komponenty CalculatorButton
takto:
<template> <div v-if="displayValue === 'C'" class="calculator-button calculator-button-operator"> {{ displayValue }} </div> <div v-else class="calculator-button"> {{ displayValue }} </div> </template> <script> export default { name: 'CalculatorButton', props: { displayValue: { type: String, required: true } } } </script> <style scoped> .calculator-button { display: flex; justify-content: center; align-items: center; padding: .75em; font-size: 1.5rem; font-weight: bold; flex: 0 0 auto; width: 60px; cursor: pointer; transition: all .3s ease-in-out; } .calculator-button:not(.calculator-button-operator) { background: transparent } .calculator-button:not(.calculator-button-operator):hover { background: #F2EDCF; } .calculator-button:active { transform: scale(.85); box-shadow: 0px 0px 0px 1px rgba(0, 0, 0, .15) } .calculator-button-operator { background: #fee8d7; } .calculator-button-operator:hover { background: #FDDDC3; } </style>
Ve webovém prohlížeči nyní vidíme, že tlačítko "C" má tmavší barvu pozadí než ostatní:
Komponenta zobrazuje vždy jeden ze dvou elementů <div>
,
které jsou nakódovány v šabloně, a to podle vyhodnocení podmínky
obsažené v direktivě v-if
.
V další lekci, Computed properties a dynamické styly ve Vue, se seznámíme s tzv. computed properties a naučíme se stylovat komponenty a HTML elementy dynamicky.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 46x (35.3 MB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript