IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 5 - Tvorba OOP diáře v JavaScriptu

V minulé lekci, Referenční a hodnotové datové typy v JavaScriptu, jsme si vysvětlili rozdíly mezi hodnotovými a referenčními datovými typy. Již víme, že když uložíme instanci třídy do nějaké proměnné, je v ní ve skutečnosti uložena reference (odkaz) na tuto instanci. Můžeme tak používat jednu instanci z několika proměnných nebo ji jednoduše předávat, aniž by se zkopírovala.

Jak jsem slíbil, v dnešním tutoriálu objektově orientovaného programování v JavaScriptu začneme programovat elektronický diář. Využijeme zde také znalosti z minula.

Příprava

Nejdříve se ale zamyslíme nad tím, co vše budeme potřebovat. Vytvoříme si jednoduchou stránku, index.html, s formulářem na přidání záznamu nahoře a výpisem záznamů dole. Do nějakého kontejneru, např. do elementu <div>, si vložíme dva inputy. Budou typu "text" a "date" na název úkolu a jeho datum. Nakonec ještě přidáme tlačítko na potvrzení. Níže přidáme druhý <div> na seznam úkolů.

Co se týče JavaScriptu, můžeme si vytvořit složku js/ a v ní tři skripty: Diar.js, Zaznam.js a obsluha.js. Rovnou je v naší stránce i naodkazujeme.

Soubor index.html by tedy mohl vypadat takto:

<!DOCTYPE html>
<html lang="cs-cz">
<head>
    <meta charset="UTF-8">
    <title>Diář</title>
</head>
<body>
    <h1>Diář</h1>
    <div>
        <input type="text" id="nazev" placeholder="Vyplňte název úkolu"><br>
        <input type="date" id="datum" placeholder="Vyplňte datum"><br>
        <button id="potvrdit">Uložit úkol</button>
    </div>
    <div id="seznam-ukolu">

    </div>
    <script src="js/Diar.js"></script>
    <script src="js/Zaznam.js"></script>
    <script src="js/obsluha.js"></script>
</body>
</html>

Stránka by mohla vypadat takto:

Tvoje stránka
localhost

Vzhled nyní nebudeme příliš řešit.

Záznam

Začneme se souborem Zaznam.js. Jak asi tušíte, soubor bude obsahovat třídu reprezentující jeden záznam v našem diáři. Můžeme jí tedy dát různé vlastnosti, které při vytvoření a po vytvoření záznamu budeme moci měnit. Zatím to může být název, datum a zda byl úkol splněn. První dva parametry nastavíme konstruktorem a co se týká splněnosti úkolu, tak budeme předpokládat, že je po vytvoření vždy nesplněný:

class Zaznam {

    constructor(nazev, datum) {
        this.nazev = nazev;
        this.datum = datum;
        this.splneno = false;
    }

}

Diář

Přesuňme se nyní k samotnému diáři.

Konstruktor

V souboru Diar.js si vytvoříme třídu Diar s konstruktorem a v něm nadefinujeme několik vlastností:

  • zaznamy - Záznamy diáře vytvoříme jako prázdné pole.
  • jazyk - Jazyk výpisu data (datumů) záznamů se nám může v budoucnu hodit, jelikož různé jazyky mají různé formáty. Např. české datum vypadá jinak než anglické. Pro nastavení jazyka přidáme do konstruktoru parametr. Protože budeme chtít většinou české prostředí, definujeme mu výchozí hodnotu "cs-CZ", která se použije pokud parametr nezadáme.

Třída by zatím mohla vypadat takto:

class Diar {

    constructor(jazyk = "cs-CZ") {
        this.zaznamy = [];
        this.jazyk = jazyk;
    }

}

Vybírání elementů na stránce

Ve třídě budeme potřebovat pracovat s DOM elementy na stránce. Možná jste se již setkali s principem oddělení práce s logikou od práce s uživatelským rozhraním. Tohoto základního programátorského pravidla využívá např. architektura MVC.

V javascriptových frameworcích, ke kterým se dostanete po tomto kurzu, je architektura aplikace postavená tak, aby se nemíchal kód vybírající elementy na stránce s dalším kódem aplikace. Bylo by to totiž velmi nepřehledné.

My si v základním OOP kurzu nebudeme vytvářet žádnou komplikovanou architekturu, ale budeme se snažit umístit vybírání elementů ze stránky na jedno jediné místo ve třídě. Tímto místem bude právě konstruktor. Vytvoříme si zde několik dalších vlastností a do nich uložíme elementy ze stránky, které budeme ve třídě dále potřebovat:

  • nazevInput - Input element s názvem nově přidávaného záznamu.
  • datumInput - Input element s datem nově přidávaného záznamu.
  • potvrditButton - Ukládací tlačítko.
  • vypisElement - Element pro výpis záznamů uložených v diáři.

Konstruktor bude nyní vypadat takto:

constructor(jazyk = "cs-CZ") {
    this.zaznamy = [];
    this.jazyk = jazyk;

    this.nazevInput = document.getElementById("nazev");
    this.datumInput = document.getElementById("datum");
    this.potvrditButton = document.getElementById("potvrdit");
    this.vypisElement = document.getElementById("seznam-ukolu");
}

Nikam jinam ve třídě nebudeme dále vkládat žádný další výběr elementů, protože by to bylo velmi nepřehledné.

Metody

Přejděme k metodám diáře.

nastavUdalosti()

Aby náš konstruktor nebyl příliš dlouhý, vyčleníme nastavení obslužných událostí elementům na stránce do oddělené metody. V našem případě jde jen o obsluhu kliknutí na tlačítko.

Zatím si přidejme naivní implementaci metody pro obsluhu tlačítka, která nebude fungovat. Proč si vysvětlíme za okamžik:

nastavUdalosti() {
    this.potvrditButton.onclick = function() { // tento kód nebude fungovat
        const zaznam = new Zaznam(this.nazevInput.value, this.datumInput.value);
        this.zaznamy.push(zaznam);
        this.vypisZaznamy();
    };
}

Metoda na událost onclick tlačítka this.potvrditButton naváže obslužnou funkci. Zde je ještě vše v pořádku. Uvnitř se vezmou hodnoty z inputů a na jejich základě se vytvoří nový záznam. Tuto novou instanci vložíme do pole. Všechny záznamy poté vypíšeme.

Co je tedy špatně? Pokud jste dávali v Základních konstrukcích JavaScriptu pozor, víte, že:

Při použití function pro obsluhu událostí elementů se mění kontext a klíčové slovo this následně ukazuje na element, který událost způsobil. this tedy přestane obsahovat instanci naší třídy. Toto chování je chyba v návrhu jazyka JavaScript a zabraňuje nám pracovat s instančními proměnnými a metodami v obsluze událostí.

Arrow functions

Způsobů, jak tento problém obejít, je hned několik. My si zmíníme to nejjednodušší řešení. K obsluze události použijeme tzv. arrow function, což je "zkrácený" zápis funkce. Název vychází ze znaku šipky (anglicky arrow), kterým se tyto funkce zapisují. Arrow functions byly do JavaScriptu přidány až později a proto chybou změny kontextu již netrpí. Přesněji ani žádný svůj kontext nemají a klíčové slovo this v nich obsahuje to, co v něm bylo předtím, beze změny.

Arrow function do nějaké proměnné uložíme následujícím způsobem:

nazevFunkce = () => {
    // tělo funkce
}

Pokud bychom chtěli funkci poslat i parametry, můžeme je psát do závorek, jak jsme zvyklí:

nazevFunkce = (parametr) => {
    // tělo funkce
}

Pokud bychom chtěli poslat pouze jeden, můžeme závorky dokonce i vynechat:

nazevFunkce = parametr => {
    // tělo funkce
}

Nyní tedy metodu nastavUdalosti() opravíme, aby v obslužné funkci fungovalo klíčové slovo this. To totiž používáme k přístupu k vlastnostem naší třídy:

nastavUdalosti() {
    this.potvrditButton.onclick = () => { // this zůstane nyní stále this
        const zaznam = new Zaznam(this.nazevInput.value, this.datumInput.value);
        this.zaznamy.push(zaznam);
        this.vypisZaznamy();
    };
}

Metodu zavoláme na konci konstruktoru:

this.nastavUdalosti();

vypisZaznamy()

V metodě pro výpis úkolů nás asi nic nepřekvapí, funguje velmi podobně jako výpis zaměstnanců, který jsme vytvářeli v předešlých lekcích:

vypisZaznamy() {
    this.vypisElement.innerHTML = "";
    for (let i = 0; i < this.zaznamy.length; i++) {
        const zaznam = this.zaznamy[i];
        this.vypisElement.innerHTML += `<h3>${zaznam.nazev}</h3>kdy: ${zaznam.datum}<br>splněno: ${zaznam.splneno}`;
    }
}

Metoda smaže veškerý obsah z našeho elementu a vypíše tam postupně naše úkoly pomocí cyklu.

Obsluha

Nakonec musíme ještě v obsluha.js vytvořit instanci třídy Diar a vypsat uložené záznamy. Ty tam ve chvíli vytvoření diáře ještě nejsou, ale dále v kurzu je budeme načítat z lokálního úložiště:

const diar = new Diar();
diar.vypisZaznamy();

Pokud nyní naší aplikaci spustíme v prohlížeči, bude vypadat takto:

Tvoje stránka
localhost

V případě jakýchkoli problému si svůj kód porovnejte s funkčním řešením v příloze.

V následujícím cvičení, Řešené úlohy k 4.-5. lekci OOP v JavaScriptu, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

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 673x (1.86 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

Předchozí článek
Referenční a hodnotové datové typy v JavaScriptu
Všechny články v sekci
Objektově orientované programování v JavaScriptu
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 4.-5. lekci OOP v JavaScriptu
Článek pro vás napsal Šimon Raichl
Avatar
Uživatelské hodnocení:
207 hlasů
Autor se věnuje hlavně tvorbě všemožných věcí v JS
Aktivity