5. diel - Computed properties a dynamické štýly vo Vue.js
V predchádzajúcej lekcii, Podmienky a cykly vo Vue.js , sme sa naučili zobrazovať HTML
elementy alebo Vue komponenty podmienečne a v cykloch. Zoznámili sme sa s
direktívami v-for
, v-if
, v-else
a
v-else-if
.
Dnes si ukážeme špecifické použitie direktívy v-bind pre atribúty class a style, computed properties, princíp reaktivity
Computed properties
Vue komponenty vo väčšine prípadov obsahujú dáta. Niektoré z nich sú
definované priamo v kóde danej komponenty (spomeňme na vlastnosť
data
konfiguračného objektu), iná sú komponente odovzdávaná z
rodičovskej komponenty prostredníctvom Props.
Medzi týmito dvoma dátovými zdrojmi je jeden zásadný rozdiel. Kým
data
môžu svoje hodnoty rôzne meniť (najčastejšie k tomu
dochádza v metódach konfiguračného objektu, o ktorých bude reč neskôr),
hodnoty Props sú vo vnútri komponenty nemenné. Ak
by sme sa kdekoľvek v kóde pokúsili o zmenu hodnoty niektoré z
Props, Vue zobrazí na konzole chybové hlásenie a kód nebude
fungovať.
Ak potrebujeme niektorú hodnotu z Props meniť, respektíve ju
použiť k ďalším výpočtom, oceníme iste ďalší nástroj, ktorý nám
framework Vue ponúka - computed properties. Ide o ďalší
vlastnosť konfiguračného objektu s názvom computed
. Jej obsahom
musí byť objekt obsahujúci iba metódy. Každá táto
metóda musí povinne vracať hodnotu a môže pracovať s
dátami alebo Props danej komponenty. K nim pristupuje pomocou
this
, ktoré v tomto prípade referuje samotnú komponent. Zápis
this.something
teda odkazuje na dátovú hodnotu danej komponenty s
názvom something
, či už bola definovaná v Props, v
dátach, alebo v computed properties.
Z toho logicky vyplýva ďalšie pravidlo. Názvy jednotlivých premenných musí byť unikátne v celej komponente, názov, ktorý bol použitý napríklad v Props, už nejde druhýkrát použiť v dátach ani v computed properties pod.
Ukážme si fungovanie computed properties na jednoduchom príklade:
<template> <div>{{ fullName }}</div> </template> <script> export default { name: 'FullName', props: { firstName: { required: true, type: String }, lastName: { required: true, type: String } }, computed: { fullName () { return this.firstName + ' ' + this.lastName } } } </script>
Tento komponent dostáva od svojej rodičovskej komponenty dve hodnoty v
Props: firstName
a lastName
. V computed
properties je potom definovaná nová hodnota - fullName
ako
výpočet z oboch predchádzajúcich. Tá je potom zobrazovaná v šablóne.
Komponent by sme mohli použiť napríklad takto:
<template> <div> <full-name first-name="Honza" last-name="Novák"/> <full-name first-name="Pepa" last-name="Horák"/> </div> </template> <script> import FullName from '@/components/FullName.vue' export default { components: { FullName } } </script>
Tento kód by zobrazil dve celé mená - "Honza Novák" a "Pepa Horák".
Príklad sa vám iste môže zdať triviálne, zmysel využitie computed properties však rastie s náročnosťou výpočtu či aplikačnej logiky. Je tiež dôležité vziať do úvahy, že hodnoty computed properties sú automaticky prepočítané zakaždým, keď sa zmení niektorá vstupná hodnota pre ich výpočet. Keď uvážime, že hodnoty môžu byť odovzdávané z rodičovských do dcérskych komponentov dynamicky, potom je zrejmé, že nám computed properties výrazne uľahčujú prácu.
Direktíva v-bind:class
Pripomeňme si, že direktíva v-bind
priraďuje hodnotu
obsiahnutého JavaScriptového výrazu, ktorý môže obsahovať premenné danej
komponenty, do Props komponenty dcérskej alebo priamo do atribútu
HTML elementu. Medzi HTML atribúty však existujú dve výnimky, kedy je
potrebné použiť odlišnú syntax - atribúty class
a
style
. Vue nám umožňuje dynamicky priraďovať CSS triedy do
atribútu class
dvoma spôsobmi:
Objektová syntaxe
V objekte, ktorý je priradený direktíve v-bind
, definujeme
CSS triedy ako názvy jednotlivých vlastností. Hodnoty týchto vlastností sú
JavaScriptové výrazy, ktoré sa po vyhodnotení ako pravdivé
(Truth), je trieda danému elementu priradená, v opačnom prípade
nie.
<div :class=" { 'class-name': condition, { 'another-class': anotherCondition } "> </div>
Vyššie uvedeným kódom priraďujeme jednotlivé CSS triedy elementu
<div>
podmienečne. Ak je výraz condition
pravdivý, bude classList elementu div
obsahovať CSS triedu
.class-name
. Ďalej, ak je pravdivý výraz
anotherCondition
, bude classList elementu obsahovať CSS triedu
.another-class
.
Array syntaxe
Direktíve v-bind
na atribútu class
môžeme okrem
objektu priradiť aj pole obsahujúce stringy - názvy jednotlivých CSS
tried:
<div :class="['red-border', 'light-shadow', className]"></div>
Kód vyššie priradí elementu <div>
CSS triedy
.red-border
, .light-shadow
a potom ešte tú triedu,
ktorej názov je obsiahnutý v premennej className
.
Ak potrebujeme v array syntaxi použiť podmienky, je to pomerne jednoduché. Namiesto textového reťazca môže byť prvkom poľa objekt s jednou vlastnosťou (názov triedy) a jej hodnotou (výraz - podmienka):
<div :class="['light-shadow', { 'red-border': !isValid }]"></div>
Takto napríklad priradíme elementu <div>
CSS triedu
"light-shadow" vždy a triedu "red-border" práve vtedy, keď hodnota premennej
isValid
bude nepravdivá (false).
V príkladoch oboch syntaxou sme objekty / pole vypisovali priamo do šablóny. Pomerne často je však využívaná technika, kedy sú objekty / polia vypočítané v skripte, a to najčastejšie práve v computed properties, o ktorých sme hovorili na začiatku lekcie.
Direktíva v-bind:style
Druhou výnimkou zo všeobecnej syntaxe direktívy v-bind
je
atribút style
, ktorým sú HTML elementu priraďované inline CSS
štýly.
Objektová syntaxe
Názvy CSS vlastností píšeme ako názvy vlastností objektu. Môžeme tu
však vedľa notácie kebab-case písané v jednoduchých
úvodzovkách použiť aj notáciu CamelCase. Zápisy
'border-top-color'
a borderTopColor
sú teda
ekvivalentné. Tieto vlastnosti štýlového objektu potom obsahujú
požadované hodnoty CSS vlastností (samozrejme vrátane jednotiek):
<div :style="{fontSize: size + 'px'}"></div>
Kód vyššie tak teda napríklad definuje v elemente
<div>
výšku písma (font-size
) práve toľko
pixelov, koľko je hodnota premennej size
. Nedáva Ak výraz
size + 'px'
platnú CSS hodnotu, bude tento zápis ignorovaný.
Array syntaxe
Podobne ako u v-bind:class
bývajú štýlové objekty
definované v skripte, a to najčastejšie v computed properties. Array
syntaxe nám umožňuje zlúčiť štýly niekoľkých štýlových objektov
dohromady, napríklad takto:
<div :style="[styleObject1, styleObject2]"></div>
Kalkulačka - štýlovanie tlačidiel
Teóriu vysvetlenú vyššie teraz uplatníme v našej kalkulačke. Po
minulej lekcii, kde sme si potrebovali ukázať podmienenej renderovanie,
obsahuje naša komponenta CalculatorButton
vo svojej šablóne
opakovaný kód. Opisujú tu dvakrát ten istý element
<div>
, jeho jednotlivé opakovania sa líšia iba CSS triedou
.calculator-button-operator
, ktorá v prvom výskyte obsiahnutá
nie je, v druhom áno. Pomerne nešikovne potom na základe podmienky v
direktíve v-if
zobrazujeme buď prvý alebo druhý element
<div>
.
Iste by bolo praktickejšie, rovnako tak náš kód by bol lepšie
čitateľný a udržiavateľný, keby sme vždy zobrazovali len jeden element
<div>
a vyhodnotenie podmienky by rozhodovalo iba o
priradenie danej CSS triedy.
Ďalej chceme, aby tmavšie oranžové pozadia mala všetky tlačidlá okrem položiek a desatinnej čiarky. Tieto tlačidlá budeme pracovne nazývať "operátormi".
Upravme šablónu a skript komponenty CalculatorButton
takto:
<template> <div class="calculator-button" :class="{ 'calculator-button-operator': isOperator }" > {{ displayValue }} </div> </template> <script> export default { name: 'CalculatorButton', props: { displayValue: { type: String, required: true } }, computed: { isOperator () { return this.displayValue !== ',' && isNaN(parseInt(this.displayValue)) } } } </script>
Vo scriptu sme vytvorili jednu dátovú položku v computed
properties. Jej názov je isOperator
a ide o funkciu, ktorá
vracia hodnotu false
pre tlačidlá zobrazujúci číslo alebo
desatinnú čiarku, hodnotu true
potom vracia pre všetky ostatné
tlačidlá.
V šablóne sme použili štandardné atribút class
elementu
<div>
, v ktorom tomuto elementu priraďujeme CSS triedu
.calculator-button
. Táto trieda je teda priradená vždy, v
každom tlačidle bez rozdielu. V tom istom elementu sme ďalej použili
direktívu :class
a priradili jej objekt s jedinou vlastnosťou.
Takto bude trieda .calculator-button-operator
elementu priradená
práve vtedy, keď funkcia isOperator
vráti true
.
Všimnime si, že Vue umožňuje v jedinom elementu použiť oboje -
štandardný atribút class
spolu s direktívou
:class
. Danému elementu sa v takomto prípade priradí všetky CSS
triedy definované jedným aj druhým spôsobom dohromady. U atribútu
style
direktívy :style
to funguje obdobne.
Naša kalkulačka teraz vyzerá takto:
V ďalšej lekcii sa budeme venovať udalostiam vo Vue. Predstavíme si
direktívu v-on
a naučíme sa odovzdávať dáta z dcérskych do
rodičovských komponentov emitovaním vlastných udalostí.