You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/cs/7-bank-project/1-template-route/README.md

15 KiB

Vytvoření bankovní aplikace, část 1: HTML šablony a trasy ve webové aplikaci

Kvíz před lekcí

Kvíz před lekcí

Úvod

Od vzniku JavaScriptu v prohlížečích se webové stránky stávají interaktivnějšími a složitějšími než kdy dříve. Webové technologie se nyní běžně používají k vytváření plně funkčních aplikací, které běží přímo v prohlížeči, a nazýváme je webové aplikace. Protože jsou webové aplikace vysoce interaktivní, uživatelé nechtějí čekat na úplné načtení stránky pokaždé, když provedou nějakou akci. Proto se používá JavaScript k přímé aktualizaci HTML pomocí DOM, aby se zajistil plynulejší uživatelský zážitek.

V této lekci položíme základy pro vytvoření bankovní webové aplikace, přičemž použijeme HTML šablony k vytvoření více obrazovek, které lze zobrazit a aktualizovat bez nutnosti znovu načítat celou HTML stránku.

Předpoklady

Pro testování webové aplikace, kterou v této lekci vytvoříme, potřebujete lokální webový server. Pokud ho nemáte, můžete si nainstalovat Node.js a použít příkaz npx lite-server ve složce svého projektu. Tím vytvoříte lokální webový server a otevřete svou aplikaci v prohlížeči.

Příprava

Na svém počítači vytvořte složku nazvanou bank a uvnitř ní soubor index.html. Začneme s tímto HTML základem:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bank App</title>
  </head>
  <body>
    <!-- This is where you'll work -->
  </body>
</html>

HTML šablony

Pokud chcete vytvořit více obrazovek pro webovou stránku, jedním řešením by bylo vytvořit jeden HTML soubor pro každou obrazovku, kterou chcete zobrazit. Toto řešení však přináší určité nevýhody:

  • Při přepínání obrazovek musíte znovu načíst celé HTML, což může být pomalé.
  • Je obtížné sdílet data mezi různými obrazovkami.

Dalším přístupem je mít pouze jeden HTML soubor a definovat více HTML šablon pomocí elementu <template>. Šablona je znovupoužitelný HTML blok, který není prohlížečem zobrazen a musí být instancován za běhu pomocí JavaScriptu.

Úkol

Vytvoříme bankovní aplikaci se dvěma obrazovkami: přihlašovací stránkou a dashboardem. Nejprve přidáme do těla HTML prvek zástupce, který použijeme k instancování různých obrazovek naší aplikace:

<div id="app">Loading...</div>

Dáváme mu atribut id, aby bylo později snazší ho najít pomocí JavaScriptu.

Tip: protože obsah tohoto prvku bude nahrazen, můžeme do něj vložit zprávu o načítání nebo indikátor, který se zobrazí, zatímco se aplikace načítá.

Dále přidáme pod tento prvek HTML šablonu pro přihlašovací stránku. Prozatím do ní vložíme pouze nadpis a sekci obsahující odkaz, který použijeme k navigaci.

<template id="login">
  <h1>Bank App</h1>
  <section>
    <a href="/dashboard">Login</a>
  </section>
</template>

Poté přidáme další HTML šablonu pro stránku dashboardu. Tato stránka bude obsahovat různé sekce:

  • Hlavičku s nadpisem a odkazem pro odhlášení
  • Aktuální zůstatek na bankovním účtu
  • Seznam transakcí, zobrazený v tabulce
<template id="dashboard">
  <header>
    <h1>Bank App</h1>
    <a href="/login">Logout</a>
  </header>
  <section>
    Balance: 100$
  </section>
  <section>
    <h2>Transactions</h2>
    <table>
      <thead>
        <tr>
          <th>Date</th>
          <th>Object</th>
          <th>Amount</th>
        </tr>
      </thead>
      <tbody></tbody>
    </table>
  </section>
</template>

Tip: při vytváření HTML šablon, pokud chcete vidět, jak budou vypadat, můžete zakomentovat řádky <template> a </template> tím, že je obklopíte <!-- -->.

Proč myslíte, že používáme atributy id na šablonách? Mohli bychom použít něco jiného, například třídy?

Zobrazení šablon pomocí JavaScriptu

Pokud zkusíte aktuální HTML soubor v prohlížeči, uvidíte, že se zasekne na zobrazení Loading.... To je proto, že musíme přidat nějaký JavaScriptový kód, který instancuje a zobrazí HTML šablony.

Instancování šablony se obvykle provádí ve 3 krocích:

  1. Získání elementu šablony v DOM, například pomocí document.getElementById.
  2. Klonování elementu šablony pomocí cloneNode.
  3. Připojení k DOM pod viditelný prvek, například pomocí appendChild.

Proč musíme šablonu klonovat, než ji připojíme k DOM? Co si myslíte, že by se stalo, kdybychom tento krok přeskočili?

Úkol

Vytvořte nový soubor nazvaný app.js ve složce svého projektu a importujte tento soubor do sekce <head> svého HTML:

<script src="app.js" defer></script>

Nyní v app.js vytvoříme novou funkci updateRoute:

function updateRoute(templateId) {
  const template = document.getElementById(templateId);
  const view = template.content.cloneNode(true);
  const app = document.getElementById('app');
  app.innerHTML = '';
  app.appendChild(view);
}

To, co zde děláme, jsou přesně 3 kroky popsané výše. Instancujeme šablonu s id templateId a vložíme její klonovaný obsah do našeho zástupce aplikace. Všimněte si, že musíme použít cloneNode(true), abychom zkopírovali celý podstrom šablony.

Nyní zavolejte tuto funkci s jednou ze šablon a podívejte se na výsledek.

updateRoute('login');

Jaký je účel tohoto kódu app.innerHTML = '';? Co se stane bez něj?

Vytváření tras

Když mluvíme o webové aplikaci, nazýváme trasování záměr mapovat URL na konkrétní obrazovky, které by měly být zobrazeny. Na webové stránce s více HTML soubory se to děje automaticky, protože cesty k souborům se odrážejí v URL. Například s těmito soubory ve složce vašeho projektu:

mywebsite/index.html
mywebsite/login.html
mywebsite/admin/index.html

Pokud vytvoříte webový server s mywebsite jako kořen, mapování URL bude:

https://site.com            --> mywebsite/index.html
https://site.com/login.html --> mywebsite/login.html
https://site.com/admin/     --> mywebsite/admin/index.html

Nicméně pro naši webovou aplikaci používáme jeden HTML soubor obsahující všechny obrazovky, takže nám toto výchozí chování nepomůže. Musíme tuto mapu vytvořit ručně a aktualizovat zobrazenou šablonu pomocí JavaScriptu.

Úkol

Použijeme jednoduchý objekt k implementaci mapy mezi cestami URL a našimi šablonami. Přidejte tento objekt na začátek svého souboru app.js.

const routes = {
  '/login': { templateId: 'login' },
  '/dashboard': { templateId: 'dashboard' },
};

Nyní trochu upravíme funkci updateRoute. Místo toho, abychom přímo předávali templateId jako argument, chceme ho získat nejprve pohledem na aktuální URL a poté použít naši mapu k získání odpovídající hodnoty templateId. Můžeme použít window.location.pathname k získání pouze části cesty z URL.

function updateRoute() {
  const path = window.location.pathname;
  const route = routes[path];

  const template = document.getElementById(route.templateId);
  const view = template.content.cloneNode(true);
  const app = document.getElementById('app');
  app.innerHTML = '';
  app.appendChild(view);
}

Zde jsme mapovali trasy, které jsme deklarovali, na odpovídající šablonu. Můžete vyzkoušet, že to funguje správně, změnou URL ručně ve svém prohlížeči.

Co se stane, když zadáte neznámou cestu do URL? Jak bychom to mohli vyřešit?

Přidání navigace

Dalším krokem pro naši aplikaci je přidání možnosti navigace mezi stránkami bez nutnosti ručně měnit URL. To zahrnuje dvě věci:

  1. Aktualizaci aktuálního URL
  2. Aktualizaci zobrazené šablony na základě nového URL

Druhou část jsme již vyřešili pomocí funkce updateRoute, takže musíme zjistit, jak aktualizovat aktuální URL.

Budeme muset použít JavaScript a konkrétně history.pushState, který umožňuje aktualizovat URL a vytvořit nový záznam v historii prohlížení, aniž by se znovu načítalo HTML.

Poznámka: Zatímco HTML prvek kotvy <a href> může být použit samostatně k vytvoření hypertextových odkazů na různé URL, ve výchozím nastavení způsobí, že prohlížeč znovu načte HTML. Je nutné tomuto chování zabránit při manipulaci s trasováním pomocí vlastního JavaScriptu, použitím funkce preventDefault() na události kliknutí.

Úkol

Vytvořme novou funkci, kterou můžeme použít k navigaci v naší aplikaci:

function navigate(path) {
  window.history.pushState({}, path, path);
  updateRoute();
}

Tato metoda nejprve aktualizuje aktuální URL na základě zadané cesty a poté aktualizuje šablonu. Vlastnost window.location.origin vrací kořen URL, což nám umožňuje rekonstruovat kompletní URL ze zadané cesty.

Nyní, když máme tuto funkci, můžeme se postarat o problém, který máme, pokud cesta neodpovídá žádné definované trase. Upravením funkce updateRoute přidáme záložní trasu na jednu z existujících tras, pokud nemůžeme najít shodu.

function updateRoute() {
  const path = window.location.pathname;
  const route = routes[path];

  if (!route) {
    return navigate('/login');
  }

  ...

Pokud nelze najít trasu, nyní přesměrujeme na stránku login.

Nyní vytvořme funkci pro získání URL při kliknutí na odkaz a zabránění výchozímu chování prohlížeče při kliknutí na odkaz:

function onLinkClick(event) {
  event.preventDefault();
  navigate(event.target.href);
}

Dokončeme navigační systém přidáním vazeb na naše odkazy Login a Logout v HTML.

<a href="/dashboard" onclick="onLinkClick(event)">Login</a>
...
<a href="/login" onclick="onLinkClick(event)">Logout</a>

Objekt event výše zachytí událost click a předá ji naší funkci onLinkClick.

Pomocí atributu onclick připojte událost click k JavaScriptovému kódu, zde volání funkce navigate().

Zkuste kliknout na tyto odkazy, nyní byste měli být schopni navigovat mezi různými obrazovkami své aplikace.

Metoda history.pushState je součástí standardu HTML5 a je implementována ve všech moderních prohlížečích. Pokud vytváříte webovou aplikaci pro starší prohlížeče, existuje trik, který můžete použít místo této API: použití hash (#) před cestou vám umožní implementovat trasování, které funguje s běžnou navigací kotvy a nenačítá stránku znovu, protože jeho účelem bylo vytvořit interní odkazy na stránce.

Řešení tlačítek zpět a vpřed v prohlížeči

Použití history.pushState vytváří nové záznamy v historii navigace prohlížeče. Můžete to zkontrolovat podržením tlačítka zpět svého prohlížeče, mělo by zobrazit něco jako toto:

Screenshot historie navigace

Pokud zkusíte několikrát kliknout na tlačítko zpět, uvidíte, že se aktuální URL mění a historie se aktualizuje, ale stále se zobrazuje stejná šablona.

To je proto, že aplikace neví, že je potřeba zavolat updateRoute() pokaždé, když se historie změní. Pokud se podíváte na dokumentaci history.pushState, můžete vidět, že pokud se stav změní - což znamená, že jsme se přesunuli na jiné URL - je spuštěna událost popstate. Použijeme to k vyřešení tohoto problému.

Úkol

Abychom zajistili, že zobrazená šablona bude aktualizována, když se historie prohlížeče změní, připojíme novou funkci, která volá updateRoute(). Uděláme to na konci našeho souboru app.js:

window.onpopstate = () => updateRoute();
updateRoute();

Poznámka: zde jsme použili arrow function k deklaraci našeho obslužného programu události popstate pro stručnost, ale běžná funkce by fungovala stejně.

Zde je video o arrow funkcích:

Arrow Functions

🎥 Klikněte na obrázek výše pro video o arrow funkcích.

Nyní zkuste použít tlačítka zpět a vpřed svého prohlížeče a zkontrolujte, že zobrazená trasa je tentokrát správně aktualizována.


🚀 Výzva

Přidejte novou šablonu a trasu pro třetí stránku, která zobrazuje kredity této aplikace.

Kvíz po lekci

Kvíz po lekci

Přehled a samostudium

Trasování je jednou z překvapivě složitých částí vývoje webu, zejména když se web přesouvá od chování při obnovování stránky k obnovování stránky v aplikacích typu Single Page Application. Přečtěte si něco o tom, jak služba Azure Static Web App řeší trasování. Dokážete vysvětlit, proč jsou některá rozhodnutí popsaná v tomto dokumentu nezbytná?

Zadání

Zlepšete trasování


Prohlášení:
Tento dokument byl přeložen pomocí služby pro automatický překlad Co-op Translator. I když se snažíme o přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za autoritativní zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádné nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.