15 KiB
Izrada bankovne aplikacije, 1. dio: HTML predlošci i rute u web aplikaciji
Kviz prije predavanja
Uvod
Od pojave JavaScripta u preglednicima, web stranice postaju interaktivnije i složenije nego ikad. Web tehnologije se sada često koriste za stvaranje potpuno funkcionalnih aplikacija koje se pokreću izravno u pregledniku, a nazivamo ih web aplikacijama. Budući da su web aplikacije vrlo interaktivne, korisnici ne žele čekati potpuno ponovno učitavanje stranice svaki put kada se izvrši neka radnja. Zato se JavaScript koristi za ažuriranje HTML-a izravno putem DOM-a, kako bi se pružilo glatko korisničko iskustvo.
U ovoj lekciji postavit ćemo temelje za izradu bankovne web aplikacije, koristeći HTML predloške za stvaranje više ekrana koji se mogu prikazivati i ažurirati bez potrebe za ponovnim učitavanjem cijele HTML stranice.
Preduvjeti
Trebat će vam lokalni web poslužitelj za testiranje web aplikacije koju ćemo izraditi u ovoj lekciji. Ako ga nemate, možete instalirati Node.js i koristiti naredbu npx lite-server
iz mape vašeg projekta. To će stvoriti lokalni web poslužitelj i otvoriti vašu aplikaciju u pregledniku.
Priprema
Na svom računalu stvorite mapu pod nazivom bank
s datotekom index.html
unutar nje. Počet ćemo s ovim HTML boilerplateom:
<!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 predlošci
Ako želite stvoriti više ekrana za web stranicu, jedno rješenje bi bilo stvoriti jednu HTML datoteku za svaki ekran koji želite prikazati. Međutim, ovo rješenje dolazi s nekim neugodnostima:
- Morate ponovno učitati cijeli HTML prilikom promjene ekrana, što može biti sporo.
- Teško je dijeliti podatke između različitih ekrana.
Drugi pristup je imati samo jednu HTML datoteku i definirati više HTML predložaka koristeći element <template>
. Predložak je višekratni HTML blok koji preglednik ne prikazuje i koji se mora instancirati u vrijeme izvođenja pomoću JavaScripta.
Zadatak
Izradit ćemo bankovnu aplikaciju s dva ekrana: stranica za prijavu i nadzorna ploča. Prvo, dodajmo u HTML tijelo element rezerviranog mjesta koji ćemo koristiti za instanciranje različitih ekrana naše aplikacije:
<div id="app">Loading...</div>
Dodijelili smo mu id
kako bismo ga kasnije lakše pronašli pomoću JavaScripta.
Savjet: budući da će sadržaj ovog elementa biti zamijenjen, možemo staviti poruku ili indikator učitavanja koji će se prikazivati dok se aplikacija učitava.
Zatim, dodajmo ispod HTML predložak za stranicu za prijavu. Za sada ćemo tamo staviti samo naslov i odjeljak koji sadrži poveznicu koju ćemo koristiti za navigaciju.
<template id="login">
<h1>Bank App</h1>
<section>
<a href="/dashboard">Login</a>
</section>
</template>
Zatim ćemo dodati još jedan HTML predložak za stranicu nadzorne ploče. Ova stranica će sadržavati različite odjeljke:
- Zaglavlje s naslovom i poveznicom za odjavu
- Trenutni saldo bankovnog računa
- Popis transakcija prikazan u tablici
<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>
Savjet: kada izrađujete HTML predloške, ako želite vidjeti kako će izgledati, možete komentirati linije
<template>
i</template>
tako da ih obuhvatite s<!-- -->
.
✅ Zašto mislite da koristimo id
atribute na predlošcima? Možemo li koristiti nešto drugo, poput klasa?
Prikazivanje predložaka pomoću JavaScripta
Ako pokušate otvoriti trenutnu HTML datoteku u pregledniku, vidjet ćete da se zaglavilo na prikazu Loading...
. To je zato što trebamo dodati JavaScript kod za instanciranje i prikazivanje HTML predložaka.
Instanciranje predloška obično se radi u 3 koraka:
- Dohvatite element predloška u DOM-u, na primjer pomoću
document.getElementById
. - Klonirajte element predloška pomoću
cloneNode
. - Priključite ga na DOM ispod vidljivog elementa, na primjer pomoću
appendChild
.
✅ Zašto trebamo klonirati predložak prije nego ga priključimo na DOM? Što mislite da bi se dogodilo ako preskočimo ovaj korak?
Zadatak
Stvorite novu datoteku pod nazivom app.js
u mapi vašeg projekta i uvezite tu datoteku u <head>
sekciju vašeg HTML-a:
<script src="app.js" defer></script>
Sada u app.js
stvorit ćemo novu funkciju 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);
}
Ovdje radimo upravo 3 koraka opisana gore. Instanciramo predložak s id
-om templateId
i stavljamo njegov klonirani sadržaj unutar našeg rezerviranog mjesta aplikacije. Napominjemo da trebamo koristiti cloneNode(true)
kako bismo kopirali cijelo podstablo predloška.
Sada pozovite ovu funkciju s jednim od predložaka i pogledajte rezultat.
updateRoute('login');
✅ Koja je svrha ovog koda app.innerHTML = '';
? Što se događa bez njega?
Stvaranje ruta
Kada govorimo o web aplikaciji, nazivamo Routing namjeru mapiranja URL-ova na određene ekrane koji bi se trebali prikazati. Na web stranici s više HTML datoteka, to se automatski radi jer se putovi datoteka odražavaju na URL. Na primjer, s ovim datotekama u mapi vašeg projekta:
mywebsite/index.html
mywebsite/login.html
mywebsite/admin/index.html
Ako stvorite web poslužitelj s mywebsite
kao korijenom, mapiranje URL-a bit će:
https://site.com --> mywebsite/index.html
https://site.com/login.html --> mywebsite/login.html
https://site.com/admin/ --> mywebsite/admin/index.html
Međutim, za našu web aplikaciju koristimo jednu HTML datoteku koja sadrži sve ekrane, pa nam ovo zadano ponašanje neće pomoći. Moramo ručno stvoriti ovu mapu i ažurirati prikazani predložak pomoću JavaScripta.
Zadatak
Koristit ćemo jednostavan objekt za implementaciju mape između URL putova i naših predložaka. Dodajte ovaj objekt na vrh vaše app.js
datoteke.
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard' },
};
Sada malo izmijenimo funkciju updateRoute
. Umjesto da izravno prosljeđujemo templateId
kao argument, želimo ga dohvatiti prvo gledajući trenutni URL, a zatim koristiti našu mapu za dobivanje odgovarajuće vrijednosti templateId
. Možemo koristiti window.location.pathname
za dobivanje samo dijela puta iz URL-a.
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);
}
Ovdje smo mapirali rute koje smo deklarirali na odgovarajući predložak. Možete provjeriti radi li ispravno tako da ručno promijenite URL u pregledniku.
✅ Što se događa ako unesete nepoznati put u URL? Kako bismo to mogli riješiti?
Dodavanje navigacije
Sljedeći korak za našu aplikaciju je dodavanje mogućnosti navigacije između stranica bez potrebe za ručnim mijenjanjem URL-a. To podrazumijeva dvije stvari:
- Ažuriranje trenutnog URL-a
- Ažuriranje prikazanog predloška na temelju novog URL-a
Drugi dio smo već riješili s funkcijom updateRoute
, pa moramo smisliti kako ažurirati trenutni URL.
Morat ćemo koristiti JavaScript, a posebno history.pushState
koji omogućuje ažuriranje URL-a i stvaranje novog unosa u povijesti pregledavanja, bez ponovnog učitavanja HTML-a.
Napomena: Iako se HTML element sidra
<a href>
može koristiti samostalno za stvaranje hiperveza na različite URL-ove, on će po zadanom učiniti da preglednik ponovno učita HTML. Potrebno je spriječiti ovo ponašanje prilikom rukovanja rutama pomoću prilagođenog JavaScripta, koristeći funkcijupreventDefault()
na događaju klika.
Zadatak
Stvorimo novu funkciju koju možemo koristiti za navigaciju u našoj aplikaciji:
function navigate(path) {
window.history.pushState({}, path, path);
updateRoute();
}
Ova metoda prvo ažurira trenutni URL na temelju zadanog puta, a zatim ažurira predložak. Svojstvo window.location.origin
vraća korijen URL-a, omogućujući nam rekonstrukciju kompletnog URL-a iz zadanog puta.
Sada kada imamo ovu funkciju, možemo riješiti problem koji imamo ako put ne odgovara nijednoj definiranoj ruti. Izmijenit ćemo funkciju updateRoute
dodavanjem povratne opcije na jednu od postojećih ruta ako ne možemo pronaći podudaranje.
function updateRoute() {
const path = window.location.pathname;
const route = routes[path];
if (!route) {
return navigate('/login');
}
...
Ako ruta ne može biti pronađena, sada ćemo preusmjeriti na stranicu login
.
Sada stvorimo funkciju za dohvaćanje URL-a kada se klikne na poveznicu i za sprječavanje zadano ponašanje preglednika za poveznice:
function onLinkClick(event) {
event.preventDefault();
navigate(event.target.href);
}
Dovršimo navigacijski sustav dodavanjem veza za naše Login i Logout poveznice u HTML-u.
<a href="/dashboard" onclick="onLinkClick(event)">Login</a>
...
<a href="/login" onclick="onLinkClick(event)">Logout</a>
Objekt event
iznad hvata događaj click
i prosljeđuje ga našoj funkciji onLinkClick
.
Koristeći atribut onclick
, povežite događaj click
s JavaScript kodom, ovdje pozivom funkcije navigate()
.
Pokušajte kliknuti na ove poveznice, sada biste trebali moći navigirati između različitih ekrana vaše aplikacije.
✅ Metoda history.pushState
dio je HTML5 standarda i implementirana je u svim modernim preglednicima. Ako izrađujete web aplikaciju za starije preglednike, postoji trik koji možete koristiti umjesto ove API-je: koristeći hash (#
) prije puta možete implementirati rute koje rade s redovnom navigacijom sidra i ne učitavaju ponovno stranicu, jer je njegova svrha bila stvaranje unutarnjih poveznica unutar stranice.
Rukovanje gumbima za povratak i naprijed u pregledniku
Korištenje history.pushState
stvara nove unose u povijesti navigacije preglednika. Možete to provjeriti držeći gumb za povratak vašeg preglednika, trebao bi prikazati nešto poput ovoga:
Ako pokušate kliknuti na gumb za povratak nekoliko puta, vidjet ćete da se trenutni URL mijenja i povijest se ažurira, ali isti predložak ostaje prikazan.
To je zato što aplikacija ne zna da trebamo pozvati updateRoute()
svaki put kada se povijest promijeni. Ako pogledate dokumentaciju za history.pushState
, možete vidjeti da ako se stanje promijeni - što znači da smo se pomaknuli na drugi URL - događaj popstate
se pokreće. Koristit ćemo to za rješavanje ovog problema.
Zadatak
Kako bismo osigurali da se prikazani predložak ažurira kada se povijest preglednika promijeni, povezat ćemo novu funkciju koja poziva updateRoute()
. To ćemo učiniti na dnu naše app.js
datoteke:
window.onpopstate = () => updateRoute();
updateRoute();
Napomena: ovdje smo koristili arrow funkciju za deklariranje našeg
popstate
event handlera radi sažetosti, ali regularna funkcija bi radila isto.
Evo osvježavajućeg videa o arrow funkcijama:
🎥 Kliknite na sliku iznad za video o arrow funkcijama.
Sada pokušajte koristiti gumbe za povratak i naprijed u pregledniku i provjerite da se prikazana ruta ispravno ažurira ovaj put.
🚀 Izazov
Dodajte novi predložak i rutu za treću stranicu koja prikazuje zasluge za ovu aplikaciju.
Kviz nakon predavanja
Pregled i samostalno učenje
Routing je jedan od iznenađujuće složenih dijelova web razvoja, posebno kako se web kreće od ponašanja osvježavanja stranica prema osvježavanju stranica u aplikacijama s jednom stranicom (Single Page Application). Pročitajte malo o kako Azure Static Web App usluga rukuje rutama. Možete li objasniti zašto su neke od odluka opisanih u tom dokumentu nužne?
Zadatak
Odricanje od odgovornosti:
Ovaj dokument je preveden pomoću AI usluge za prevođenje Co-op Translator. Iako nastojimo osigurati točnost, imajte na umu da automatski prijevodi mogu sadržavati pogreške ili netočnosti. Izvorni dokument na izvornom jeziku treba smatrati autoritativnim izvorom. Za ključne informacije preporučuje se profesionalni prijevod od strane čovjeka. Ne preuzimamo odgovornost za bilo kakve nesporazume ili pogrešne interpretacije koje proizlaze iz korištenja ovog prijevoda.