Modular - Utvikling (IM-ITK vg2) - NDLA

Hopp til innhald
Fagartikkel

Modular

Vi har ofte behov for å importere data og funksjonar frå kodebibliotek når vi skriv JavaScript. Vi kan òg lage eigne modular som kan importerast og eksporterast mellom JavaScript-filer.

Det kan ofte vere fordelaktig å dele opp JavaScript-koden i fleire filer. Det kan vere at vi ønsker å skilje ut variablar som skal vere enkle å endre på, eller at vi har funksjonar eller klassar som skal brukast av fleire websider eller program.

Dersom du har brukt Firebase, MySQL eller React på ei webside, har du sikkert sett nøkkelordet import øvst i koden, og at scriptet i HTML-fila har type="module" i script-taggen. Då er det brukt modular.

Lag din eigen modul

No skal du lage din eigen enkle modul. Først må du lage ei .js-fil. Kall fila namn.js, og legg inn denne koden:

navn.js
1let namn = "Kim";
2
3export { namn };

Lek merke til at vi bruker krøllparentes rundt variabelnamna som skal eksporterast.

Lag så ei HTML-fil i same mappe som du kallar index.html. Legg inn dei nødvendige taggane du treng for å lage ei webside. (I VS Code: skriv ! (utropsteikn) og trykk enter.) Nedst i <body>-taggen skriv du denne koden:

index.html
1<script type="module">
2
3import { namn } from "./navn.js";
4
5//Skriv ut verdien til variabelen namn
6console.log(namn);
7
8</script>

Viss du opnar index.html i nettlesaren og opnar inspiser-verktøyet, vil du sjå at Kim er skrive ut i konsollen. Prøv å endre namnet i namn.js til noko anna, og oppdater sidan. Då vil du sjå at det nye namnet blir skrive ut.

Får du feilmelding i konsollen?

Dersom du opnar HTML-fila frå harddisken (frå "Utforskar" eller "Finder"), kan du få denne feilmeldinga:

"Access to script at 'file:///(...)/namn.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https."

Dette er på grunn av ei avgrensing i Chrome-nettlesaren som gjer at nettsider berre kan referere til filer på webserverar og ikkje filer på ein harddisk. For å løyse problemet må du starte ein lokal webserver på maskina di. Den enklaste måten å gjere det på er å installere tillegget Live Preview eller Live Server i Visual Studio Code.

Eksportere og importere fleire variablar

Ein modul kan innehalde fleire datatypar. Dersom vi tek utgangspunkt i namn.js frå det førre dømet, kan vi legge til ein variabel for alder. Då blir koden slik:

namn.js
1let namn = "Kim";
2let alder = 17;
3
4export { namn, alder };

Vi kan no importere begge variablane i index.html, slik:

index.html
1<script type="module">
2
3import { namn, alder } from "./namn.js";
4
5console.log(`${namn} er ${alder} år gammal`);
6
7</script>

Konsollen i nettlesaren vil då vise Kim er 17 år gammal.

Definere klassar i eigne modular

Det er ikkje berre variablar som kan eksporterast og importerast. Vi kan eksportere alle typar data, som lister, objekt og klassar.

Det kan vere ryddig å skilje ut klassar i eigne modular. Då kan du importere klassane og berre ha koden for å opprette objekt i scriptet til nettsida. Dersom vi tek utgangspunkt i dømet om bilar, kan vi opprette fila bilar.js:

bilar.js
1class Bil {
2
3  constructor(bilmerke, modell, farge, 
4    toppfart, fart) {
5    this.bilmerke = bilmerke,
6    this.modell = modell,
7    this.farge = farge,
8    this.toppfart = toppfart,
9    this.fart = fart
10  }
11  
12  presenter() {
13    return `Denne bilen er ein ${this.farge} ${this.bilmerke} ${this.modell}, \
14med ein toppfart på ${this.toppfart} km/h. \
15Akkurat no har han ein fart på ${this.fart} km/h.`
16  }
17  
18  giGass() {
19    if (this.fart + 2 <= this.toppfart) {
20      this.fart = this.fart + 2;
21    }
22  }
23  
24}
25    
26class Elbil extends Bil {
27
28  constructor(bilmerke, modell, farge, toppfart, 
29    fart, batterikapasitet, batteristatus) {
30  
31    super(bilmerke, modell, farge, toppfart, fart);
32    this.batterikapasitet = batterikapasitet;
33    this.batteristatus = batteristatus;
34    
35  }
36  
37  presenter() {
38      return `Denne bilen er ein ${this.farge} ${this.bilmerke} ${this.modell}, \
39med ein toppfart på ${this.toppfart} km/h og batterikapasitet på ${this.batterikapasitet} kWh. \
40Akkurat no har han ein fart på ${this.fart} km/h, og batteriet er lada ${this.batteristatus}%.`
41  }
42  
43  lading() {
44    this.batteristatus = this.batteristatus + 10;
45  }
46  
47}
48
49export { Bil, Elbil };    

Då kan vi bruke desse klassane i fleire andre filer ved å importere klassane i scriptet.

index.html
1<script type="module">
2
3import {Bil, Elbil} from "./bilar.js";
4
5const bilar = [];
6
7bilar.push( new Bil("Porsche", "911", "svart", 290, 0) );                  //biler[0]
8bilar.push( new Bil("Ferrari", "F8 Spider", "raud", 340, 0) );             //biler[1]
9bilar.push( new Bil("Ford", "Mustang Mach 1", "blå", 270, 0) );            //biler[2]
10bilar.push( new Elbil("Ford", "Mustang Mach e", "grå", 180, 0, 68, 100) ); //biler[3]
11bilar.push( new Elbil("Tesla", "Model 3", "kvit", 260, 0, 50, 70) );       //biler[4]
12  
13for(let i of bilar){
14  console.log(i.presenter());
15}
16  
17</script>

Bruke modular for å skilje ut databasekopling

Dersom vi bruker ei databasekopling, kan vi skilje ut koden vi bruker for å kople til databasen i ei eiga fil. Då blir koden vår ryddigare, og vi slepp å lime inn denne koden i alle filene der vi skal bruke databasen. Dersom du til dømes skal bruke Firebase, kan du lage ein modul med databasekonfigurasjonen og eksportere databaseobjektet. I alle andre filer som bruker databasen, treng du dermed berre importere denne modulen. Denne koden kan sjå slik ut:

firebaseconfig.js
1// Importerer intitalizApp frå Firebase-app SDK
2import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.3/firebase-app.js";
3// Importerer getFirestore frå Firebase-Firestore SDK 
4import { getFirestore } from "https://www.gstatic.com/firebasejs/9.6.3/firebase-firestore.js"
5
6// Konfigurerer Firebase
7const firebaseConfig = {
8  apiKey: "_API_KEY_",
9  authDomain: "_PROJECT_ID_.firebaseapp.com",
10  projectId: "_PROJECT_ID_",
11  storageBucket: "_PROJECT_ID_.appspot.com",
12  messagingSenderId: "_SENDER_ID_",
13  appId: "_APP_ID_",
14};
15
16// Startar opp Firebase med den angitte konfigurasjonen
17const app = initializeApp(firebaseConfig);
18// Hentar ut referanse til Firestore-databasen
19const db = getFirestore();
20
21// Eksporterer databasen
22export { db };

Når du no skal bruke Firestore-databasen på nettsida di, treng du berre importere db frå firebaseconfig.js, slik:

index.html
1<script type="module">
2// Importerer databasen med Firebase-konfigurasjonen
3import { db } from "./firebaseconfig.js";
4
5// Importerer Firebase-funksjonane vi bruker i dette scriptet 
6// frå Firebase-Firestore SDK
7import { setDoc, doc } from "https://www.gstatic.com/firebasejs/9.6.3/firebase-firestore.js";
8
9// Lagar eit nytt dokument i samlinga "elevar"
10await setDoc(
11  doc(db, "elevar", "nilja"), {
12    fornamn: "Jakob",
13    etternamn: "Nilsen",
14    epost: "jakob@nilsen.net"
15  });
16
17</script>

Relatert innhald

Fagstoff
Objekt og klassar

Objekt er ein datatype i programmering der vi kan samle fleire bitar informasjon i ein og same variabel.

Fagstoff
Oppsett av Firebase og Cloud Firestore

I denne guiden vil du lære eit basisoppsett som du skal bruke vidare i modulen "Lage ei dynamisk webside med databasekopling i Firebase Cloud Firestore".

Skrive av Karl Arne Dalsaune.
Sist fagleg oppdatert 23.06.2022