NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Lekce 5 - Computed properties a dynamické styly ve Vue

V předchozí lekci, Podmínky a cykly ve Vue, jsme se naučili zobrazovat HTML elementy nebo Vue komponenty podmíněně a v cyklech. Seznámili jsme se s direktivami v-for, v-if, v-else a v-else-if.

Dnes si ukážeme specifické použití direktivy v-bind pro atributy class a style, computed properties, princip reaktivity

Computed properties

Vue komponenty ve většině případů obsahují data. Některá z nich jsou definována přímo v kódu dané komponenty (vzpomeňme na vlastnost data konfiguračního objektu), jiná jsou komponentě předávána z rodičovské komponenty prostřednictvím props.

Mezi těmito dvěma datovými zdroji je jeden zásadní rozdíl. Zatímco data mohou své hodnoty různě měnit (nejčastěji k tomu dochází v metodách konfiguračního objektu, o nichž bude řeč později), hodnoty props jsou uvnitř komponenty neměnné. Pokud bychom se kdekoli v kódu pokusili o změnu hodnoty některé z props, Vue zobrazí na konzoli chybové hlášení a kód nebude fungovat.

Potřebujeme-li některou hodnotu z props měnit, respektive ji použít k dalším výpočtům, oceníme jistě další nástroj, který nám framework Vue nabízí - computed properties. Jde o další vlastnost konfiguračního objektu s názvem computed. Jejím obsahem musí být objekt obsahující pouze metody. Každá tato metoda musí povinně vracet hodnotu a může pracovat s daty nebo props dané komponenty. K nim přistupuje pomocí this, které v tomto případě referuje samotnou komponentu. Zápis this.something tedy odkazuje na datovou hodnotu dané komponenty s názvem something, ať už byla definována v props, v datech, nebo v computed properties.

Z toho logicky vyplývá další pravidlo. Názvy jednotlivých proměnných musí být unikátní v celé komponentě, název, který byl použit například v props, již nejde podruhé použít v datech ani v computed properties apod.

Ukažme si fungování computed properties na jednoduchém příkladu:

<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>

Tato komponenta dostává od své rodičovské komponenty dvě hodnoty v props: firstName a lastName. V computed properties je pak definována nová hodnota - fullName jako výpočet z obou předchozích. Ta je potom zobrazována v šabloně. Komponentu bychom mohli použít třeba 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 dvě celá jména - "Honza Novák" a "Pepa Horák".

Příklad se vám jistě může zdát triviální, smysl využití computed properties však roste s náročností výpočtu či aplikační logiky. Je také důležité vzít v úvahu, že hodnoty computed properties jsou automaticky přepočítány pokaždé, kdy se změní některá vstupní hodnota pro jejich výpočet. Když uvážíme, že hodnoty mohou být předávány z rodičovských do dceřinných komponent dynamicky, pak je zřejmé, že nám computed properties výrazně usnadňují práci.

Direktiva v-bind:class

Připomeňme si, že direktiva v-bind přiřazuje hodnotu obsaženého JavaScriptového výrazu, který může obsahovat proměnné dané komponenty, do props komponenty dceřinné anebo přímo do atributu HTML elementu. Mezi HTML atributy však existují dvě výjimky, kdy je třeba použít odlišnou syntaxi - atributy class a style. Vue nám umožňuje dynamicky přiřazovat CSS třídy do atributu class dvěma způsoby:

Objektová syntaxe

V objektu, který je přiřazen direktivě v-bind, definujeme CSS třídy jako názvy jednotlivých vlastností. Hodnoty těchto vlastností jsou JavaScriptové výrazy, které se po vyhodnocení jako pravdivé (truthy), je třída danému elementu přiřazena, v opačném případě nikoliv.

<div :class="
  { 'class-name': condition,
  { 'another-class': anotherCondition }
">
</div>

Výše uvedeným kódem přiřazujeme jednotlivé CSS třídy elementu <div> podmíněně. Je-li výraz condition pravdivý, bude classList elementu div obsahovat CSS třídu .class-name. Dále, je-li pravdivý výraz anotherCondition, bude classList elementu obsahovat CSS třídu .another-class.

Array syntaxe

Direktivě v-bind na atributu class můžeme kromě objektu přiřadit i pole obsahující stringy - názvy jednotlivých CSS tříd:

<div :class="['red-border', 'light-shadow', className]"></div>

Kód výše přiřadí elementu <div> CSS třídy .red-border, .light-shadow a pak ještě tu třídu, jejíž název je obsažen v proměnné className.

Potřebujeme-li v array syntaxi použít podmínky, je to poměrně snadné. Namísto textového řetězce může být prvkem pole objekt s jednou vlastností (název třídy) a její hodnotou (výraz - podmínka):

<div :class="['light-shadow', { 'red-border': !isValid }]"></div>

Takto například přiřadíme elementu <div> CSS třídu "light-shadow" vždy a třídu "red-border" právě tehdy, když hodnota proměnné isValid bude nepravdivá (falsy).

V příkladech obou syntaxí jsme objekty/pole vypisovali přímo do šablony. Poměrně často je však využívána technika, kdy jsou objekty/pole vypočítány ve skriptu, a to nejčastěji právě v computed properties, o nichž jsme hovořili na začátku lekce.

Direktiva v-bind:style

Druhou výjimkou z obecné syntaxe direktivy v-bind je atribut style, kterým jsou HTML elementu přiřazovány inline CSS styly.

Objektová syntaxe

Názvy CSS vlastností píšeme jako názvy vlastností objektu. Můžeme zde však vedle notace kebab-case psané v jednoduchých uvozovkách použít i notaci camelCase. Zápisy 'border-top-color' a borderTopColor jsou tedy ekvivalentní. Tyto vlastnosti stylového objektu pak obsahují požadované hodnoty CSS vlastností (samozřejmě včetně jednotek):

<div :style="{fontSize: size + 'px'}"></div>

Kód výše tak tedy například definuje v elementu <div> výšku písma (font-size) právě tolik pixelů, kolik je hodnota proměnné size. Nedává-li výraz size + 'px' platnou CSS hodnotu, bude tento zápis ignorován.

Array syntaxe

Podobně jako u v-bind:class bývají stylové objekty definované ve skriptu, a to nejčastěji v computed properties. Array syntaxe nám umožňuje sloučit styly několika stylových objektů dohromady, například takto:

<div :style="[styleObject1, styleObject2]"></div>

Kalkulačka - stylování tlačítek

Teorii vysvětlenou výše nyní uplatníme v naší kalkulačce. Po minulé lekci, kde jsme si potřebovali ukázat podmíněné renderování, obsahuje naše komponenta CalculatorButton ve své šabloně opakovaný kód. Opisujeme zde dvakrát tentýž element <div>, jeho jednotlivá opakování se liší pouze CSS třídou .calculator-button-operator, která v prvním výskytu obsažena není, ve druhém ano. Poměrně nešikovně potom na základě podmínky v direktivě v-if zobrazujeme buď první nebo druhý element <div>.

Jistě by bylo praktičtější, stejně tak náš kód by byl lépe čitelný a udržovatelný, kdybychom vždy zobrazovali jen jeden element <div> a vyhodnocení podmínky by rozhodovalo pouze o přiřazení dané CSS třídy.

Dále chceme, aby tmavší oranžové pozadí měla všechna tlačítka kromě čísel a desetinné čárky. Tato tlačítka budeme pracovně nazývat "operátory".

Upravme šablonu 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>

Ve scriptu jsme vytvořili jednu datovou položku v computed properties. Její název je isOperator a jde o funkci, která vrací hodnotu false pro tlačítka zobrazující číslo nebo desetinnou čárku, hodnotu true potom vrací pro všechna ostatní tlačítka.

V šabloně jsme použili standardní atribut class elementu <div>, ve kterém tomuto elementu přiřazujeme CSS třídu .calculator-button. Tato třída je tedy přiřazena vždy, v každém tlačítku bez rozdílu. V tomtéž elementu jsme dále použili direktivu :class a přiřadili jí objekt s jedinou vlastností. Takto bude třída .calculator-button-operator elementu přiřazena právě tehdy, když funkce isOperator vrátí true.

Všimněme si, že Vue umožňuje v jediném elementu použít obojí - standardní atribut class spolu s direktivou :class. Danému elementu se v takovém případě přiřadí všechny CSS třídy definované jedním i druhým způsobem dohromady. U atributu style a direktivy :style to funguje obdobně.

Naše kalkulačka nyní vypadá takto:

Vue

V další lekci se budeme věnovat událostem ve Vue. Představíme si direktivu v-on a naučíme se předávat data z dceřiných do rodičovských komponent emitováním vlastních událostí.


 

Měl jsi s čímkoli problém? Zdrojový kód vzorové aplikace je ke stažení každých pár lekcí. Zatím pokračuj dál, a pak si svou aplikaci porovnej se vzorem a snadno oprav.

Předchozí článek
Podmínky a cykly ve Vue
Všechny články v sekci
Vue
Přeskočit článek
(nedoporučujeme)
Události ve Vue
Článek pro vás napsal Tomáš Glabazňa
Avatar
Uživatelské hodnocení:
31 hlasů
Aktivity