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/sl/7-bank-project/3-data
Lee Stott 2daab5271b
Update Quiz Link
3 weeks ago
..
README.md Update Quiz Link 3 weeks ago
assignment.md 🌐 Update translations via Co-op Translator 3 weeks ago

README.md

Ustvarjanje bančne aplikacije, 3. del: Metode pridobivanja in uporabe podatkov

Predhodni kviz

Predhodni kviz

Uvod

Jedro vsake spletne aplikacije so podatki. Podatki lahko obstajajo v različnih oblikah, vendar je njihov glavni namen prikazovanje informacij uporabniku. Z naraščajočo interaktivnostjo in kompleksnostjo spletnih aplikacij je način, kako uporabnik dostopa do informacij in z njimi interagira, postal ključni del razvoja spletnih aplikacij.

V tej lekciji bomo videli, kako asinhrono pridobiti podatke s strežnika in jih uporabiti za prikaz informacij na spletni strani, ne da bi morali ponovno naložiti HTML.

Predpogoji

Za to lekcijo morate imeti izdelan obrazec za prijavo in registracijo kot del spletne aplikacije. Prav tako morate namestiti Node.js in lokalno zagnati strežniški API, da pridobite podatke o računih.

Preverite, ali strežnik pravilno deluje, tako da v terminalu zaženete naslednji ukaz:

curl http://localhost:5000/api
# -> should return "Bank API v1.0.0" as a result

AJAX in pridobivanje podatkov

Tradicionalne spletne strani posodabljajo prikazano vsebino, ko uporabnik izbere povezavo ali pošlje podatke prek obrazca, tako da ponovno naložijo celotno HTML stran. Vsakič, ko je treba naložiti nove podatke, spletni strežnik vrne povsem novo HTML stran, ki jo mora brskalnik obdelati, kar prekine trenutno dejanje uporabnika in omeji interakcije med nalaganjem. Ta način delovanja imenujemo večstranska aplikacija ali MPA.

Potek posodobitve v večstranski aplikaciji

Ko so spletne aplikacije postale bolj kompleksne in interaktivne, se je pojavila nova tehnika, imenovana AJAX (Asynchronous JavaScript and XML). Ta tehnika omogoča, da spletne aplikacije pošiljajo in pridobivajo podatke s strežnika asinhrono z uporabo JavaScripta, ne da bi bilo treba ponovno naložiti HTML stran, kar omogoča hitrejše posodobitve in bolj gladke interakcije z uporabnikom. Ko so novi podatki pridobljeni s strežnika, je mogoče trenutno HTML stran posodobiti z JavaScriptom z uporabo DOM API-ja. Sčasoma se je ta pristop razvil v to, kar danes imenujemo enostranska aplikacija ali SPA.

Potek posodobitve v enostranski aplikaciji

Ko je bil AJAX prvič predstavljen, je bil edini API za asinhrono pridobivanje podatkov XMLHttpRequest. Vendar pa sodobni brskalniki zdaj podpirajo bolj priročen in zmogljiv Fetch API, ki uporablja obljube (promises) in je bolje prilagojen za obdelavo podatkov v obliki JSON.

Čeprav vsi sodobni brskalniki podpirajo Fetch API, je vedno dobro preveriti tabelo združljivosti na caniuse.com, če želite, da vaša spletna aplikacija deluje tudi v starejših brskalnikih.

Naloga

V prejšnji lekciji smo implementirali obrazec za registracijo za ustvarjanje računa. Zdaj bomo dodali kodo za prijavo z obstoječim računom in pridobivanje njegovih podatkov. Odprite datoteko app.js in dodajte novo funkcijo login:

async function login() {
  const loginForm = document.getElementById('loginForm')
  const user = loginForm.user.value;
}

Začnemo z iskanjem elementa obrazca z getElementById(), nato pa pridobimo uporabniško ime iz vnosa z loginForm.user.value. Vsak kontrolnik obrazca je mogoče dostopati prek njegovega imena (določenega v HTML-ju z atributom name) kot lastnosti obrazca.

Podobno kot pri registraciji bomo ustvarili drugo funkcijo za izvedbo zahteve strežniku, tokrat za pridobivanje podatkov o računu:

async function getAccount(user) {
  try {
    const response = await fetch('//localhost:5000/api/accounts/' + encodeURIComponent(user));
    return await response.json();
  } catch (error) {
    return { error: error.message || 'Unknown error' };
  }
}

Uporabimo fetch API za asinhrono zahtevo podatkov s strežnika, vendar tokrat ne potrebujemo dodatnih parametrov, razen URL-ja, saj samo poizvedujemo podatke. Privzeto fetch ustvari HTTP zahtevo GET, kar je točno tisto, kar potrebujemo.

encodeURIComponent() je funkcija, ki pobegne posebne znake za URL. Kakšne težave bi lahko imeli, če te funkcije ne pokličemo in neposredno uporabimo vrednost user v URL-ju?

Zdaj posodobimo našo funkcijo login, da uporabi getAccount:

async function login() {
  const loginForm = document.getElementById('loginForm')
  const user = loginForm.user.value;
  const data = await getAccount(user);

  if (data.error) {
    return console.log('loginError', data.error);
  }

  account = data;
  navigate('/dashboard');
}

Ker je getAccount asinhrona funkcija, jo moramo združiti z ključnimi besedami await, da počakamo na rezultat strežnika. Kot pri vsaki zahtevi strežniku se moramo ukvarjati tudi s primeri napak. Za zdaj bomo dodali le sporočilo v dnevnik, da prikažemo napako, in se k temu vrnili kasneje.

Nato moramo podatke shraniti nekam, da jih lahko kasneje uporabimo za prikaz informacij na nadzorni plošči. Ker spremenljivka account še ne obstaja, bomo na vrhu naše datoteke ustvarili globalno spremenljivko:

let account = null;

Ko so uporabniški podatki shranjeni v spremenljivko, lahko preidemo s strani login na dashboard z uporabo funkcije navigate(), ki jo že imamo.

Nazadnje moramo poklicati našo funkcijo login, ko je obrazec za prijavo oddan, tako da spremenimo HTML:

<form id="loginForm" action="javascript:login()">

Preverite, ali vse deluje pravilno, tako da registrirate nov račun in poskusite prijavo z istim računom.

Preden nadaljujemo na naslednji del, lahko dokončamo funkcijo register, tako da na dno funkcije dodamo to:

account = result;
navigate('/dashboard');

Ali ste vedeli, da privzeto lahko kličete strežniške API-je samo z iste domene in porta, kot je spletna stran, ki jo gledate? To je varnostni mehanizem, ki ga uveljavljajo brskalniki. Ampak počakajte, naša spletna aplikacija deluje na localhost:3000, medtem ko strežniški API deluje na localhost:5000. Zakaj deluje? Z uporabo tehnike, imenovane Cross-Origin Resource Sharing (CORS), je mogoče izvajati zahteve HTTP med različnimi izvoroma, če strežnik doda posebne glave v odgovor, ki omogočajo izjeme za določene domene.

Več o API-jih lahko izveste v tej lekciji.

Posodobitev HTML-ja za prikaz podatkov

Zdaj, ko imamo uporabniške podatke, moramo posodobiti obstoječi HTML, da jih prikažemo. Že vemo, kako pridobiti element iz DOM-a, na primer z document.getElementById(). Ko imate osnovni element, so tukaj nekateri API-ji, ki jih lahko uporabite za njegovo spreminjanje ali dodajanje otroških elementov:

  • Z uporabo lastnosti textContent lahko spremenite besedilo elementa. Upoštevajte, da spreminjanje te vrednosti odstrani vse otroške elemente (če obstajajo) in jih nadomesti z danim besedilom. Tako je to tudi učinkovit način za odstranitev vseh otrok določenega elementa z dodelitvijo praznega niza ''.

  • Z uporabo document.createElement() skupaj z metodo append() lahko ustvarite in pritrdite enega ali več novih otroških elementov.

Z uporabo lastnosti innerHTML elementa je prav tako mogoče spremeniti njegovo HTML vsebino, vendar se je tej treba izogibati, saj je ranljiva za napade cross-site scripting (XSS).

Naloga

Preden nadaljujemo na zaslon nadzorne plošče, moramo na strani login narediti še eno stvar. Trenutno, če poskusite prijavo z uporabniškim imenom, ki ne obstaja, se sporočilo prikaže v konzoli, vendar za običajnega uporabnika nič ne spremeni in ne veste, kaj se dogaja.

Dodajmo element z rezerviranim mestom v obrazcu za prijavo, kjer lahko po potrebi prikažemo sporočilo o napaki. Dober kraj bi bil tik pred gumbom za prijavo <button>:

...
<div id="loginError"></div>
<button>Login</button>
...

Ta element <div> je prazen, kar pomeni, da na zaslonu ne bo prikazano nič, dokler mu ne dodamo vsebine. Prav tako mu dodelimo id, da ga lahko enostavno pridobimo z JavaScriptom.

Vrnite se v datoteko app.js in ustvarite novo pomožno funkcijo updateElement:

function updateElement(id, text) {
  const element = document.getElementById(id);
  element.textContent = text;
}

Ta funkcija je precej preprosta: glede na id elementa in besedilo bo posodobila besedilno vsebino DOM elementa z ustreznim id. Uporabimo to metodo namesto prejšnjega sporočila o napaki v funkciji login:

if (data.error) {
  return updateElement('loginError', data.error);
}

Zdaj, če poskusite prijavo z neveljavnim računom, bi morali videti nekaj takega:

Posnetek zaslona, ki prikazuje sporočilo o napaki med prijavo

Zdaj imamo besedilo o napaki, ki se prikaže vizualno, vendar če ga poskusite z bralnikom zaslona, boste opazili, da se nič ne napove. Da bi besedilo, ki je dinamično dodano na stran, napovedali bralniki zaslona, mora uporabljati nekaj, kar se imenuje Live Region. Tukaj bomo uporabili posebno vrsto live regije, imenovano opozorilo:

<div id="loginError" role="alert"></div>

Enako vedenje implementirajte za napake funkcije register (ne pozabite posodobiti HTML-ja).

Prikaz informacij na nadzorni plošči

Z uporabo istih tehnik, ki smo jih pravkar videli, bomo poskrbeli tudi za prikaz informacij o računu na strani nadzorne plošče.

Tako izgleda objekt računa, pridobljen s strežnika:

{
  "user": "test",
  "currency": "$",
  "description": "Test account",
  "balance": 75,
  "transactions": [
    { "id": "1", "date": "2020-10-01", "object": "Pocket money", "amount": 50 },
    { "id": "2", "date": "2020-10-03", "object": "Book", "amount": -10 },
    { "id": "3", "date": "2020-10-04", "object": "Sandwich", "amount": -5 }
  ],
}

Opomba: da si olajšate delo, lahko uporabite že obstoječi račun test, ki je že napolnjen s podatki.

Naloga

Začnimo z zamenjavo razdelka "Balance" v HTML-ju, da dodamo elemente z rezerviranim mestom:

<section>
  Balance: <span id="balance"></span><span id="currency"></span>
</section>

Dodali bomo tudi nov razdelek tik pod tem, da prikažemo opis računa:

<h2 id="description"></h2>

Ker opis računa deluje kot naslov za vsebino pod njim, je označen semantično kot naslov. Več o tem, kako je struktura naslovov pomembna za dostopnost, in kritično preglejte stran, da ugotovite, kaj bi še lahko bilo naslov.

Nato bomo v app.js ustvarili novo funkcijo za zapolnitev rezerviranih mest:

function updateDashboard() {
  if (!account) {
    return navigate('/login');
  }

  updateElement('description', account.description);
  updateElement('balance', account.balance.toFixed(2));
  updateElement('currency', account.currency);
}

Najprej preverimo, ali imamo potrebne podatke o računu, preden nadaljujemo. Nato uporabimo funkcijo updateElement(), ki smo jo ustvarili prej, za posodobitev HTML-ja.

Da bi bil prikaz stanja lepši, uporabimo metodo toFixed(2), da prisilimo prikaz vrednosti z 2 decimalnima mestoma.

Zdaj moramo poklicati našo funkcijo updateDashboard() vsakič, ko je nadzorna plošča naložena. Če ste že dokončali nalogo iz lekcije 1, bi moralo biti to enostavno, sicer lahko uporabite naslednjo implementacijo.

Dodajte to kodo na konec funkcije updateRoute():

if (typeof route.init === 'function') {
  route.init();
}

In posodobite definicijo poti z:

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

S to spremembo se funkcija updateDashboard() pokliče vsakič, ko je prikazana stran nadzorne plošče. Po prijavi bi morali nato videti stanje računa, valuto in opis.

Dinamično ustvarjanje vrstic tabele z HTML predlogami

V prvi lekciji smo uporabili HTML predloge skupaj z metodo appendChild() za implementacijo navigacije v naši aplikaciji. Predloge so lahko tudi manjše in se uporabljajo za dinamično zapolnjevanje ponavljajočih se delov strani.

Uporabili bomo podoben pristop za prikaz seznama transakcij v HTML tabeli.

Naloga

Dodajte novo predlogo v <body> HTML-ja:

<template id="transaction">
  <tr>
    <td></td>
    <td></td>
    <td></td>
  </tr>
</template>

Ta predloga predstavlja eno vrstico tabele s tremi stolpci, ki jih želimo zapolniti: datum, objekt in znesek transakcije.

Nato dodajte to lastnost id elementu <tbody> tabele znotraj predloge nadzorne plošče, da ga lažje najdete z JavaScriptom:

<tbody id="transactions"></tbody>

Naš HTML je pripravljen, preklopimo na JavaScript kodo in ustvarimo novo funkcijo createTransactionRow:

function createTransactionRow(transaction) {
  const template = document.getElementById('transaction');
  const transactionRow = template.content.cloneNode(true);
  const tr = transactionRow.querySelector('tr');
  tr.children[0].textContent = transaction.date;
  tr.children[1].textContent = transaction.object;
  tr.children[2].textContent = transaction.amount.toFixed(2);
  return transactionRow;
}

Ta funkcija naredi točno to, kar njen naziv nakazuje: z uporabo predloge, ki smo jo ustvarili prej, ustvari novo vrstico tabele in zapolni njeno vsebino z podatki o transakciji. To bomo uporabili v naši funkciji updateDashboard() za zapolnitev tabele:

const transactionsRows = document.createDocumentFragment();
for (const transaction of account.transactions) {
  const transactionRow = createTransactionRow(transaction);
  transactionsRows.appendChild(transactionRow);
}
updateElement('transactions', transactionsRows);

Tukaj uporabimo metodo document.createDocumentFragment(), ki ustvari nov DOM fragment, na katerem lahko delamo, preden ga končno pritrdimo na našo HTML tabelo.

Še vedno moramo narediti eno stvar, preden lahko ta koda deluje, saj naša funkcija updateElement() trenutno podpira samo besedilno vsebino. Spremenimo njeno kodo:

function updateElement(id, textOrNode) {
  const element = document.getElementById(id);
  element.textContent = ''; // Removes all children
  element.append(textOrNode);
}

Uporabimo metodo append(), saj omogoča pritrditev bodisi besedila bodisi DOM vozlišč na starševski element, kar je popolno za vse naše primere uporabe. Če poskusite uporabiti račun test za prijavo, bi morali zdaj na nadzorni plošči videti seznam transakcij 🎉.


🚀 Izziv

Sodelujte in poskrbite, da bo stran nadzorne plošče videti kot prava bančna aplikacija. Če ste svojo aplikacijo že oblikovali, poskusite uporabiti media queries, da ustvarite odziven dizajn, ki bo dobro deloval tako na namiznih kot na mobilnih napravah.

Tukaj je primer oblikovane strani nadzorne plošče:

Posnetek zaslona primera rezultata nadzorne plošče po oblikovanju

Kviz po predavanju

Kviz po predavanju

Naloga

Refaktorirajte in komentirajte svojo kodo


Omejitev odgovornosti:
Ta dokument je bil preveden z uporabo storitve za prevajanje z umetno inteligenco Co-op Translator. Čeprav si prizadevamo za natančnost, vas prosimo, da upoštevate, da lahko avtomatizirani prevodi vsebujejo napake ali netočnosti. Izvirni dokument v njegovem maternem jeziku je treba obravnavati kot avtoritativni vir. Za ključne informacije priporočamo profesionalni človeški prevod. Ne prevzemamo odgovornosti za morebitna nesporazumevanja ali napačne razlage, ki bi nastale zaradi uporabe tega prevoda.