Menu-komponentin luominen

Ennen navigoinnin lisäämistä toteutetaan ensin Menu-komponentin pohja, jonka päälle navigointi toteutetaan.

Ladataan ensin navigoinnissa käytettävät kuvakkeet:

  1. Lataa osoitteesta https://www.svgrepo.com/svg/23967/lemon löytyvä kuvake SVG-muodossa ja tallenna se src/assets-kansioon nimellä lemon.svg.
  2. Lataa osoitteesta https://www.svgrepo.com/svg/409249/package löytyvä kuvake SVG-muodossa ja tallenna se src/assets-kansioon nimellä package.svg.
  3. Lataa osoitteesta https://www.svgrepo.com/svg/509221/settings löytyvä kuvake SVG-muodossa ja tallenna se src/assets-kansioon nimellä settings.svg.

Lisää src/components-kansioon uusi Menu.jsx-niminen tiedosto ja liitä sen sisällöksi seuraava ohjelmakoodi:

import iconLemon from '../assets/lemon.svg';
import iconPackage from '../assets/package.svg';
import iconSettings from '../assets/settings.svg';

function Menu(props) {

  return (
    <div className="menu">
      <div>
        <img src={iconLemon} alt="main" />
      </div>
      <div>
        <img src={iconPackage} alt="store" />
      </div>
      <div>
        <img src={iconSettings} alt="settings" />
      </div>
    </div>
  );
  
}
  
export default Menu;

Samalla kun otetaan Menu-komponentti käyttöön, niin kääritään samalla sivun sisältöä sivun asemointia määrittelevien elementtien sisälle. Muokkaa src-kansiossa olevaa App.jsx-tiedostoa. Lisää tiedoston alkuun ensin seuraava tuontilause:

import Menu from './components/Menu';

Muuta sen jälkeen return-lause seuraavanlaiseksi:

  return (
    <div className="root">
      <div className="root_content">
        <div className="container clicker">
          <Header>lemon clicker</Header>
          <Balance total={clicks} />
          <Lemon onClick={handleClick} />
          <Booster value="3.2" />
        </div>
      </div>
      <Menu />
    </div>  
  )

Tämä muutos lisäsi useamman div-elementin, jotka toimivat sisällön kääreinä.

  • root-luokan tehtävänä on määritellä sovelluksen koko. Tyylimääritteissä on asetettu sovellukselle maksimi- ja minimileveydet, joita leveämmäksi ja kapeammaksi sovellus ei saa laajentua tai supistua. Lisäksi luokassa määritellään, että sovellus käyttää pystysuunnassa koko ikkunan korkeuden.
  • Sivun yksilöllinen sisältö kääritään root_content-luokan sisälle. Luokan tyyliasetukset huolehtivat siitä, että sisältö katkaistaan alareunasta, jos sisällön korkeus kasvaa käytettävää tila-aluetta korkeammaksi.
  • container-luokka huolehtii siitä, että sisältö sijoittuu halutulla tavalla. Lähtökohtaisesti sisältö juoksutetaan ylhäältä alaspäin.

Tämän muutoksen jälkeen selaimessa toimiva sovellus muistuttaa hyvin pitkälle alkuperäistä suunnitelmaa.

Menu-komponentti toteutettu

Sisällön ehdollinen renderöinti

Suunnitelmassa paketti-ikonin päällä oli pieni merkki, joka kertoo ostettavissa olevien lisäosien määrän. Toteutetaan tämä toiminnallisuus seuraavaksi.

Avaa src/components-kansion Menu.jsx-tiedosto ja muuta return-lause seuraavanlaiseksi:

  return (
    <div className="menu">
      <div>
        <img src={iconLemon} alt="main" />
      </div>
      <div>
        <img src={iconPackage} alt="store" />
        { props.items ? <span className="menu_badge">{props.items}</span> : null }
      </div>
      <div>
        <img src={iconSettings} alt="settings" />
      </div>
    </div>
  );

Ohjelmakoodi pysyi muuten muuttumattomana, mutta pakettikuvan alle lisättiin uusi rivi. Tuolla rivillä hyödynnetään kolmiosaista ehdollista operaattoria (?: eli ternary operator). Ensimmäisessä osassa on ehto, joka perusteella toteutuu joko toinen tai kolmas osa. Rakenteeltaan tuo rivi vastaa if-else-rakennetta, mutta kolmiosaista operaattoria käytettäessä ehdollisuus saadaan näppärästi upotettua osaksi JSX-koodia.

Kooditasolla tuolla rivillä tarkistetaan ensin, onko props.items-muuttujalla jokin arvo. Tässä on hyvä muistaa, että JavaScriptissä tyhjästä ja arvosta 0 poikkeavat arvot saavat totuusarvon tosi. Toisin sanoen, ensimmäisestä osasta tulee tosi, kun arvo on jokin muu kuin 0. Toisessa osassa oleva span-elementti renderöidään silloin, kun ensimmäisen osan tulos on tosi (eli arvo on nollasta poikkeava). Kolmannen osan null eli tyhjä renderöidään jos ensimmäisessä osan tulos oli epätosi eli arvo on nolla.

Tyylimääritteet puolestaan huolehtivat siitä, että mahdollisesti renderöitävä span-elementti näyttää halutunlaiselta ja se sijoittuu ikonin oikeaan yläkulmaan.

Tarkistetaan vielä, että tekemämme muutos Menu-komponentissa toimii halutulla tavalla. Muokkaa src-kansion App.jsx-tiedostossa Menu-komponentin kutsu seuraavanlaiseksi:

      <Menu items={2} />

Tämän muutoksen jälkeen sovelluksen menuosiossa paketti-ikonin päälle ilmestyi merkki kertomaan ostettavien lisäosien määrää.

merkki Menu-komponentin  ikonissa

Muutosten vienti versiohallintaan

Viedään viimeisimmät muutokset versiohallintaan.

git add .
git commit -m "lisää Menu-komponentin ja kääre-elementit"

lisää Menu-komponentin ja kääre-elementit -commit