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/fi/7-bank-project/1-template-route/README.md

15 KiB

Rakenna pankkisovellus Osa 1: HTML-mallit ja reitit verkkosovelluksessa

Ennakkokysely

Ennakkokysely

Johdanto

JavaScriptin tulon myötä selaimiin verkkosivustoista on tullut entistä vuorovaikutteisempia ja monimutkaisempia. Verkkoteknologioita käytetään nykyään yleisesti täysin toimivien sovellusten luomiseen, jotka toimivat suoraan selaimessa. Näitä kutsutaan verkkosovelluksiksi. Koska verkkosovellukset ovat erittäin vuorovaikutteisia, käyttäjät eivät halua odottaa koko sivun uudelleenlatausta jokaisen toiminnon yhteydessä. Siksi JavaScriptiä käytetään päivittämään HTML suoraan DOM:n avulla, jotta käyttäjäkokemus olisi sujuvampi.

Tässä oppitunnissa luomme perustan pankkisovelluksen rakentamiselle käyttämällä HTML-malleja useiden näyttöjen luomiseen, joita voidaan näyttää ja päivittää ilman koko HTML-sivun uudelleenlatausta.

Esitiedot

Tarvitset paikallisen verkkopalvelimen testataksesi verkkosovellusta, jonka rakennamme tällä oppitunnilla. Jos sinulla ei ole sellaista, voit asentaa Node.js:n ja käyttää komentoa npx lite-server projektikansiostasi. Tämä luo paikallisen verkkopalvelimen ja avaa sovelluksesi selaimessa.

Valmistelu

Luo tietokoneellesi kansio nimeltä bank ja sen sisälle tiedosto nimeltä index.html. Aloitamme tästä HTML-pohjasta:

<!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-mallit

Jos haluat luoda verkkosivulle useita näyttöjä, yksi ratkaisu olisi luoda yksi HTML-tiedosto jokaiselle näytölle. Tämä ratkaisu tuo kuitenkin mukanaan joitakin haittoja:

  • Koko HTML täytyy ladata uudelleen näytön vaihtuessa, mikä voi olla hidasta.
  • Tietojen jakaminen eri näyttöjen välillä on vaikeaa.

Toinen lähestymistapa on käyttää vain yhtä HTML-tiedostoa ja määritellä useita HTML-malleja <template>-elementin avulla. Malli on uudelleenkäytettävä HTML-lohko, jota selain ei näytä, ja se täytyy ottaa käyttöön ajonaikaisesti JavaScriptin avulla.

Tehtävä

Luomme pankkisovelluksen, jossa on kaksi näyttöä: kirjautumissivu ja hallintapaneeli. Aloitetaan lisäämällä HTML-runkoon paikkamerkki, jota käytämme sovelluksemme eri näyttöjen näyttämiseen:

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

Annamme sille id-tunnisteen, jotta se on helpompi löytää JavaScriptillä myöhemmin.

Vinkki: Koska tämän elementin sisältö korvataan, voimme laittaa siihen latausviestin tai -indikaattorin, joka näkyy sovelluksen latautuessa.

Seuraavaksi lisätään HTML-malli kirjautumissivulle. Toistaiseksi laitamme siihen vain otsikon ja osion, joka sisältää linkin navigointia varten.

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

Lisätään sitten toinen HTML-malli hallintapaneelisivulle. Tämä sivu sisältää eri osioita:

  • Otsikko, jossa on otsikko ja uloskirjautumislinkki
  • Pankkitilin nykyinen saldo
  • Tapahtumaluettelo, joka näytetään taulukossa
<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>

Vinkki: Kun luot HTML-malleja, jos haluat nähdä, miltä ne näyttävät, voit kommentoida <template>- ja </template>-rivien ympärille <!-- -->.

Miksi luulet, että käytämme id-attribuutteja malleissa? Voisimmeko käyttää jotain muuta, kuten luokkia?

Mallien näyttäminen JavaScriptillä

Jos kokeilet nykyistä HTML-tiedostoasi selaimessa, huomaat, että se jää näyttämään Loading.... Tämä johtuu siitä, että meidän täytyy lisätä JavaScript-koodia mallien käyttöönottoon ja näyttämiseen.

Mallin käyttöönotto tehdään yleensä kolmessa vaiheessa:

  1. Haetaan mallielementti DOM:sta, esimerkiksi käyttämällä document.getElementById.
  2. Kopioidaan mallielementti käyttämällä cloneNode.
  3. Liitetään se DOM:iin näkyvän elementin alle, esimerkiksi käyttämällä appendChild.

Miksi meidän täytyy kopioida malli ennen sen liittämistä DOM:iin? Mitä luulet tapahtuvan, jos ohitamme tämän vaiheen?

Tehtävä

Luo uusi tiedosto nimeltä app.js projektikansioosi ja tuo tämä tiedosto HTML:n <head>-osioon:

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

Nyt app.js-tiedostossa luomme uuden funktion 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);
}

Tässä teemme juuri yllä kuvatut kolme vaihetta. Otamme käyttöön mallin, jonka id on templateId, ja laitamme sen kopioidun sisällön sovelluksemme paikkamerkkiin. Huomaa, että meidän täytyy käyttää cloneNode(true) kopioidaksemme koko mallin alipuusto.

Kutsu nyt tätä funktiota yhdellä mallilla ja katso tulosta.

updateRoute('login');

Mikä on tämän koodin app.innerHTML = ''; tarkoitus? Mitä tapahtuu ilman sitä?

Reittien luominen

Kun puhumme verkkosovelluksesta, kutsumme reititykseksi tarkoitusta yhdistää URL-osoitteet tiettyihin näyttöihin, jotka pitäisi näyttää. Verkkosivustolla, jossa on useita HTML-tiedostoja, tämä tapahtuu automaattisesti, koska tiedostopolut heijastuvat URL-osoitteeseen. Esimerkiksi, jos projektikansiossasi on nämä tiedostot:

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

Jos luot verkkopalvelimen, jonka juurena on mywebsite, URL-yhdistykset ovat:

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

Kuitenkin verkkosovelluksessamme käytämme yhtä HTML-tiedostoa, joka sisältää kaikki näytöt, joten tämä oletuskäyttäytyminen ei auta meitä. Meidän täytyy luoda tämä kartta manuaalisesti ja päivittää näytettävä malli JavaScriptin avulla.

Tehtävä

Käytämme yksinkertaista objektia toteuttamaan kartan URL-polkujen ja malliemme välillä. Lisää tämä objekti app.js-tiedostosi alkuun.

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

Muokataan nyt hieman updateRoute-funktiota. Sen sijaan, että välittäisimme suoraan templateId:n argumenttina, haluamme hakea sen ensin nykyisestä URL-osoitteesta ja käyttää sitten karttaamme saadaksemme vastaavan mallin id:n arvon. Voimme käyttää window.location.pathname saadaksemme vain polkuosan URL-osoitteesta.

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);
}

Tässä yhdistimme määritellyt reitit vastaaviin malleihin. Voit kokeilla, että tämä toimii oikein, muuttamalla URL-osoitetta selaimessasi manuaalisesti.

Mitä tapahtuu, jos syötät tuntemattoman polun URL-osoitteeseen? Kuinka voisimme ratkaista tämän?

Navigoinnin lisääminen

Seuraava askel sovelluksessamme on lisätä mahdollisuus navigoida sivujen välillä ilman, että URL-osoitetta tarvitsee muuttaa manuaalisesti. Tämä tarkoittaa kahta asiaa:

  1. Päivitetään nykyinen URL-osoite
  2. Päivitetään näytettävä malli uuden URL-osoitteen perusteella

Olemme jo huolehtineet toisesta osasta updateRoute-funktion avulla, joten meidän täytyy selvittää, kuinka päivittää nykyinen URL-osoite.

Meidän täytyy käyttää JavaScriptiä ja tarkemmin sanottuna history.pushState, joka mahdollistaa URL-osoitteen päivittämisen ja uuden merkinnän luomisen selaushistoriaan ilman HTML:n uudelleenlatausta.

Huom: Vaikka HTML-ankkurielementti <a href> voidaan käyttää itsenäisesti luomaan hyperlinkkejä eri URL-osoitteisiin, se lataa oletuksena HTML:n uudelleen. Tämä käyttäytyminen täytyy estää, kun käsittelemme reititystä mukautetulla JavaScriptillä, käyttämällä preventDefault()-funktiota klikkaustapahtumassa.

Tehtävä

Luodaan uusi funktio, jota voimme käyttää navigointiin sovelluksessamme:

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

Tämä metodi päivittää ensin nykyisen URL-osoitteen annetun polun perusteella ja sitten päivittää mallin. Ominaisuus window.location.origin palauttaa URL-osoitteen juuren, mikä mahdollistaa täydellisen URL-osoitteen uudelleenrakentamisen annetusta polusta.

Nyt kun meillä on tämä funktio, voimme huolehtia ongelmasta, joka ilmenee, jos polku ei vastaa mitään määriteltyä reittiä. Muokkaamme updateRoute-funktiota lisäämällä varasuunnitelman yhteen olemassa olevista reiteistä, jos emme löydä vastaavuutta.

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

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

  ...

Jos reittiä ei löydy, ohjaamme nyt login-sivulle.

Luodaan nyt funktio, joka hakee URL-osoitteen, kun linkkiä klikataan, ja estää selaimen oletuslinkkikäyttäytymisen:

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

Viimeistellään navigointijärjestelmä lisäämällä sidonnat HTML:n Login- ja Logout-linkkeihin.

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

Yllä oleva event-objekti tallentaa click-tapahtuman ja välittää sen onLinkClick-funktiollemme.

Käyttämällä onclick-attribuuttia sidomme click-tapahtuman JavaScript-koodiin, tässä tapauksessa navigate()-funktion kutsuun.

Kokeile klikata näitä linkkejä, sinun pitäisi nyt pystyä navigoimaan sovelluksesi eri näyttöjen välillä.

history.pushState-metodi on osa HTML5-standardia ja toteutettu kaikissa moderneissa selaimissa. Jos rakennat verkkosovellusta vanhemmille selaimille, voit käyttää tämän API:n sijasta kikkaa: käyttämällä hash-merkkiä (#) ennen polkua voit toteuttaa reitityksen, joka toimii tavallisella ankkurinavigoinnilla eikä lataa sivua uudelleen, sillä sen tarkoitus oli luoda sisäisiä linkkejä sivun sisällä.

Selaimen takaisin- ja eteenpäin-painikkeiden käsittely

history.pushState luo uusia merkintöjä selaimen navigointihistoriaan. Voit tarkistaa tämän pitämällä selaimen takaisin-painiketta painettuna, jolloin sen pitäisi näyttää jotain tällaista:

Navigointihistorian kuvakaappaus

Jos yrität klikata takaisin-painiketta muutaman kerran, huomaat, että nykyinen URL-osoite muuttuu ja historia päivittyy, mutta sama malli pysyy näytöllä.

Tämä johtuu siitä, että sovellus ei tiedä, että meidän täytyy kutsua updateRoute() aina, kun historia muuttuu. Jos katsot history.pushState-dokumentaatiota, huomaat, että jos tila muuttuu - eli siirrymme eri URL-osoitteeseen - popstate-tapahtuma laukaistaan. Käytämme tätä ongelman korjaamiseen.

Tehtävä

Jotta varmistamme, että näytettävä malli päivittyy, kun selaimen historia muuttuu, liitämme uuden funktion, joka kutsuu updateRoute(). Teemme tämän app.js-tiedoston lopussa:

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

Huom: Käytimme tässä nuolifunktiota määrittämään popstate-tapahtumakäsittelijämme tiiviisti, mutta tavallinen funktio toimisi samalla tavalla.

Tässä on kertausvideo nuolifunktioista:

Nuolifunktiot

🎥 Klikkaa yllä olevaa kuvaa katsoaksesi videon nuolifunktioista.

Kokeile nyt käyttää selaimen takaisin- ja eteenpäin-painikkeita ja tarkista, että näytettävä reitti päivittyy oikein tällä kertaa.


🚀 Haaste

Lisää uusi malli ja reitti kolmannelle sivulle, joka näyttää tämän sovelluksen tekijätiedot.

Jälkikysely

Jälkikysely

Kertaus ja itseopiskelu

Reititys on yksi yllättävän haastavista osista verkkokehityksessä, erityisesti kun verkko siirtyy sivun uudelleenlatauskäyttäytymisestä yhden sivun sovellusten päivityksiin. Lue hieman siitä, kuinka Azure Static Web App -palvelu käsittelee reititystä. Voitko selittää, miksi jotkin kyseisessä dokumentissa kuvatut päätökset ovat tarpeellisia?

Tehtävä

Paranna reititystä


Vastuuvapauslauseke:
Tämä asiakirja on käännetty käyttämällä tekoälypohjaista käännöspalvelua Co-op Translator. Vaikka pyrimme tarkkuuteen, huomioithan, että automaattiset käännökset voivat sisältää virheitä tai epätarkkuuksia. Alkuperäinen asiakirja sen alkuperäisellä kielellä tulisi pitää ensisijaisena lähteenä. Kriittisen tiedon osalta suositellaan ammattimaista ihmiskäännöstä. Emme ole vastuussa väärinkäsityksistä tai virhetulkinnoista, jotka johtuvat tämän käännöksen käytöstä.