1

Procvičování cyklů, jednoduché komponenty

Procvičíme si cykly a naučíme se, jak v JavaScriptu vytvářet složitější HTML.

Díky JavaScriptu a práci s DOMem už dokážete vašim stránkám vdechnout hodně života a zprostředkovat tak uživateli interaktivní zážitek. Vaše aplikace tak můžou začít růst a kódu v nich bude přibývat. Abychom se ve spletitých zdrojácích dokázali vyznat, budeme se postupně učit, jak rozsekávat aplikace na samostatné funkční celky, takzvané komponenty.

Než se však pustíme do tohoto tématu, ještě si lehce zopakujeme cykly z minulé lekce.

Cvičení: Opáčko cyklů

1

Nákupní seznam

to dáš

Mějme pole řetězců představující nákupní seznam

const list = ['mouka', 'máslo', 'cukr', 'jablka', 'skořice'];
  1. Napište cyklus, který projde celé toto pole a všechny položky spojí dohromady do jednoho velkého řetězce jako níže.

    'moukamáslocukrjablkaskořice'
    
  2. Upravte váš program tak, že výsledný řetězec bude vypadat takto:

    'mouka,máslo,cukr,jablka,skořice'
    
  3. Upravte váš program tak, aby výsledný řětězec obsahoval HTML značky.

    '<li>mouka</li><li>máslo</li><li>cukr</li><li>jablka</li><li>skořice</li>'
    
  4. Vytvořte někde na stránce prázdný číslovaný seznam ol a pomocí vlastnosti innerHTML do něj vložte řetězec sestavený v předchozím kroku.

2

Nákupní seznam jako funkce

to dáš
  1. Vytvořte funkci s názvem shoppingList, která na vstupu obdrží pole řetězců, představující nákupní seznam. Funkce vrátí řetězec obsahující prvky tohoto seznamu zabalené do HTML značek li.

    Příklad použití:

    > shoppingList(['špagety', 'kečup', 'sýr']);
    '<li>špagety</li><li>kečup</li><li>sýr</li>'
    
  2. Upravte výsledek předchozího cvičení tak, že obsah číslovaného seznamu vytvoříte voláním funkce shoppingList.

První komponenta

V tomtu kurzu postupně směřujeme k tomu, abychom dokázali naši stránku sestavit z menších stavebních bloků, kterým budeme říkat komponenty. Ke skutečným komponentám se vším všudy se dostanema až ve chvíli, kdy potkáme React. Už nyní si však můžeme vyzkoušet malou ochutnávku.

Komponenta je v podstatě funkce, která dostane na vstupu nějaká data v podobě objektu, a jejím úkolem je vytvořit z těchto dat kus obsahu naší stránky. Ve cvičení Nákupní seznam jako funkce jste už ve skutečnosti něco jako komponentu vytvořili. Funkce shoppingList ze zadaného pole vytvoří kus HTML pro naši stránku na základě pole dat.

Začněme však jednodušeji a představme si, že programujeme aplikaci pro evidenci nákupních seznamů. Jednu položku takového seznamu bychom mohli reprezentavat například takto:

const item1 = {
  product: 'Rohlíky',
  amount: '10',
  bought: false,
};

Takovouto položku bychom chtěli na stránce zobrazit například takto:

<li class="item">
  <div class="item__name">Rohlíky</div>
  <div class="item__amount">10</div>
  <div class="item__bought">NE</div>
</li>

Se současnými znalostmi by nebyl problém vytvořit toto HTML pomocí následujícího kódu.

let yesNo = 'NE';
if (item1.bought) {
  yesNo = 'ANO';
}

const item1Html = `
  <li class="item">
    <div class="item__name">${item1.product}</div>
    <div class="item__amount">${item1.amount}</div>
    <div class="item__bought">${yesNo}</div>
  </li>
`

Takový kus HTML bychom pak mohli vložit někam do stránky. V naší aplikaci však budeme chtít zobrazovat víc než jednu položku. Tento kód tak budeme chtít spustit pro všechny objekty položek. Proto se nám vyplatí napsat si funkci, která na vstupu obdrží objekt položky a vrátí nám vyrobené HTML.

const ShoppingItem = (item) => {
  let yesNo = 'NE';
  if (item.bought) {
    yesNo = 'ANO';
  }

  return `
    <li class="item">
      <div class="item__name">${item.product}</div>
      <div class="item__amount">${item.amount}</div>
      <div class="item__bought">${yesNo}</div>
    </li>
  `
};

Tímto jsem vytvořili naši první komponentu! Všechny komponenty ve výsledku vypadají podobně. Komponenta vždy obdrží nějaký datový objekt, který chceme zobrazit na naší stránce, a vygeneruje HTML, které pak můžeme na stránku vložit.

Máme-li tedy stránku s prázdným seznamem jako zde

<body>
  <ol class="shopping-list"></ol>
</body>

můžeme do něj vložit jednu položku tak, že zavoláme naši komponentu.

const item1 = {
  product: 'Rohlíky',
  amount: '10',
  bought: false,
};

const listElm = document.querySelector('.shopping-list');
listElm.innerHTML += ShoppingItem(item1);

Všimněte si, že jsme funkci pojmenovali s velkým písmenem na začátku. Toto je konvence, kterou si vytvořili především React programátoři, aby dokázali rychle odlišit funkce představující komponenty od všech ostatních funkcí. JavaScriptu je úplně jedno, jaké písmenko na začátku názvu funkce uvedeme. Jde pouze o pomůcku pro nás a čtenáře našeho programu, aby všichni rychle dokázali poznat, z jakých komponent se náš program skládá. Protože v tomto kurzu směřujeme k vývoji v Reactu, budeme tuto konvenci dodržovat už od této chvíle.

Zobrazování více položek

Pokud bychom mělí více položek, vložíme je do sezanmu opakovaným voláním naší komponenty.

const item1 = {
  product: 'Rohlíky',
  amount: '10',
  bought: false,
};

const item2 = {
  product: 'Rajčate',
  amount: '1kg',
  bought: false,
};

const listElm = document.querySelector('.shopping-list');
listElm.innerHTML += ShoppingItem(item1);
listElm.innerHTML += ShoppingItem(item2);

Většinou však naše objekty budeme mít v nějakém poli. Výsledný kód by pak vypadal takto.

const items = [
  {
    product: 'Rohlíky',
    amount: '10',
    bought: false,
  },
  {
    product: 'Rajčate',
    amount: '1kg',
    bought: false,
  },
];

const listElm = document.querySelector('.shopping-list');
listElm.innerHTML += ShoppingItem(items[0]);
listElm.innerHTML += ShoppingItem(items[1]);

Takto samozřejmě nelze postupovat pokud bude objektů výrazně více. Zde si už pomůžeme cyklem.

const listElm = document.querySelector('.shopping-list');
for (let i = 0; i < items.length; i += 1) {
  listElm.innerHTML += ShoppingItem(items[i]);
}

Props

V praxi není problém psát naše komponenty tak jako výše. V Reactu však platí konvence, že vstupní objekt komponenty se vždy jmenuje props. Je to podobný princip, jako když parametr v posluchači události pojmenováváme event, i když JavaScriptu je úplně jedno, jaký název si zvolíme.

Abychom se při přechodu na React nemuseli nic přeučovat, budeme naše komponenty psát Reactovým způsobem již nyní. Naše komponenta ShoppingItem by pak vypadala takto:

const ShoppingItem = (props) => {
  let yesNo = 'NE';
  if (props.bought) {
    yesNo = 'ANO';
  }

  return `
    <li class="item">
      <div class="item__name">${props.product}</div>
      <div class="item__amount">${props.amount}</div>
      <div class="item__bought">${yesNo}</div>
    </li>
  `
};

Cvičení: Komponenty

3

Produkt

to dáš

Představte si, že tvoříte e-shop, ve kterém mají produkty následující strukturu.

const product1 = {
  name: 'Mlýnek na kávu',
  price: 520,
  currency: 'kč',
};

Postupujte dle kroků níže a vytvořte kód pro zobrazení produktu na stránce.

  1. Vytvořte HTML stránku s následující strukturu
    <body>
      <section id="products-section"></section>
      <script src="index.js"></script>
    </body>
    
  2. Na začátku souboru index.js si vytvořte objekt product1 a vymyslete si nějaký produkt s vlastnostmi name, price a currency.
  3. Ve vašem programu do proměnné productHtml sestavte HTML pro váš produkt s použitím vašeho objektu product1. Struktura může vypadat například takto.
    <div class="product">
      <h2 class="product__name">Mlýnek na kávu</h2>
      <p class="product__price">Cena: 520 kč</p>
    </div>
    
  4. Vyberte ze stránky element .products-section a vložte do něj vámi vytvořené HTML.
4

Produkt jako komponenta

to dáš

Pokračujte v předchozím cvičení.

  1. Vytvořte funkci Product, s jedním parametrem props. Tato funkce bude představovat komponentu pro jeden produkt.
  2. Do funkce Product vložte kód vytvářející HTML pro jeden produkt. Dejte pozor, že uvnitř komponenty se produkt předává v parametru props. Nechť vaše funkce jako svůj výsledek vrátí vyrobené HTML.
  3. Použijte vaši komponentu k zobrazení jednoho produktu na stránce.
  4. Vytvořte si pole products s alespoň třemi různými produkty. Pomocí cyklu toto pole projděte a pomocí vaší komponenty zobrazte na stránce každý jednotlivý produkt.
5

Hodiny

to dáš

Stáhněte si základ stránky zobrazující digitální hodiny. Následujte instrukce níže.

  1. Vytvořte komponentu Clock, která bude na vstupu očekávat takovýto objekt:
    {
      hours: 12,
      minutes: 34,
    }
    
    Komponenta nechť z takového objektu vytvoří HTML pro jedny hodiny. Jak má vypadat HTML hodin najdete v souboru index.html.
  2. HTML kód hodin ze stránky vyjměte a nechte v ní pouze element app.
  3. Ve vašem programu vyberte element app a pomocí komponenty Clock do něj zapojte hodiny zobrazující nějaký čas.
  4. Zkuste pomocí funkce Clock vložit do stránky několik různých hodin pod sebe.
  5. Zkuste vyrobit pole hodin a zobrazit je pomocí cyklu na stránce.

Doporučené úložky na doma

6

Podcasty

to dáš

Stáhněte si základ stránky zobrazující seznam epizod nějakého podcastu. Prohlédněte si HTML stránku a všimněte si, že jedna epizoda podcastu se zobrazí pomocí tohoto HTML.

<div class="episode">
  <div class="episode__num">127</div>
  <div class="episode__body">
    <div class="episode__title">Hledání plyšového Yettiho</div>
    <div class="episode__guest">host: Vojtěch Ryba</div>
  </div>
</div>
  1. Vytvořte komponentu Podcast která vyrobí HTML strukturu pro jeden podcast.
  2. V souboru index.html smažte obsah elementu episodes-list. V JavaScriptu vyberte tento element a s použitím komponenty Podcast a vlastnosti innerHTML v něm vytvořte jednu epizodu podcastu dle nějakých vymyšlených dat.
  3. Mějme následující pole obsahující několik epizod našeho podcastu.
    const episodes = [
      {
        num: 127, 
        title: 'Hledání plyšového Yettiho', 
        guest: 'Vojtěch Ryba',
      },
      {
        num: 128, 
        title: 'Moderní hrachová polévka', 
        guest: 'Kamila Štancová',
      },
      {
        num: 129, 
        title: 'Poloautomatické zrcadlo', 
        guest: 'Janka Janovská',
      },
      {
        num: 130, 
        title: 'Máčené hlavy parlamentu', 
        guest: 'Jonáš Daněk',
      },
      {
        num: 131, 
        title: 'Služby na hraně přívěsu', 
        guest: 'Tereza Křivánková',
      },
      {
        num: 132, 
        title: 'Klasifikace sněžných klokanů', 
        guest: 'Josef Stix',
      },
      {
        num: 133, 
        title: 'Rybolov v Oceánu bouří', 
        guest: 'Ludmila Gajová',
      },
    ];
    
    Napište cyklus, který projde toto pole a pro každou položku vytvoří novou epizodu uvnitř elementu episodes-list.
7

Úkolníček

zapni hlavu

Stáhněte si základ stránky zobrazující jednoduchý úkolníček.

  1. Podívejte se, jak stránka vypadá. Smažte obsah elementu todo__tasks uvnitř souboru index.html, ale zapamatujte si, jak se v HTML vytvoří jeden úkol.
  2. V JavaScriptu vytvořte pole objektů tasks, které bude reprezentovat seznam úkolů. Každý úkol bude mí zatím pouze název.
  3. Vytvořte komponentu Task, která na vstupu očekává jeden úkol a vytvoří pro něj patřičné HTML.
  4. Zavolejte funkci Task v cyklu přes pole úkolů a zapojte výsledek do vaší stránky.
  5. Vytvořte další komponentu TasksList, která na vstupu props očekává objekt obsahující pole úkolů v tomto tvaru.
      {
        tasks: [
          // array of tasks
        ]
      }
    
  6. Z HTML odstraňte celý prvek todo__tasks a nechte komponentu TasksList vytvořit celý tento prvek i s jeho obsahem. Komponenta TasksList tedy bude postupně v cyklu volat komponentu Task a vrátí HTML celého divu s třdiou todo__taska.
  7. Zavolejte funkci TasksList, předejte jí všechny úkoly v očekávaném formátu tasks a zapojte výsledek funkce do vaší stránky na konec elementu s třidou todo.