Energienetzwerke in Svelte

Dieser Kurs ist für alle, die schon immer mal ein Web-Framework kennenlernen wollten, um schneller Apps für den Browser zu entwickeln. Dafür müssen die Teilnehmenden aber schon ein Grundverständnis von HTML, CSS und Javascript mitbringen. Wir möchten den Teilnehmenden in diesem Kurs Svelte näherbringen, weil dieses Framework relativ intuitiv ist. Wenn ihr noch nie etwas von Svelte gehört habt, schaut doch mal auf der Website von Svelte vorbei.
Während des Kurses arbeiten wir mit dem Repl.it-Editor (repl.it). Dieser bietet nützlicherweise schon eine Grundkonfiguration von Svelte an, die wir während des Kurses nutzen werden.

Ziel des Kurses ist es, den Kids das Programmieren mit Svelte beizubringen und ganz nebenbei noch etwas darüber zu lernen, wie Stromnetze funktionieren. Dabei werden wir ganz einfach mit der Grundstruktur von Komponenten anfangen und uns dann über Parameter, Nesting und Events bis zum Binding vorarbeiten. Wenn ihr nicht wisst, was diese Begriffe bedeuten, schaut bitte in der Dokumentation von Svelte nach, damit ihr alles Wichtige wisst.

Bei diesem Kurs ist es sehr wichtig, auf die Fähigkeiten der Teilnehmenden einzugehen, weil "Grundkenntnisse von HTML, CSS und Javascript" für jede:n etwas Anderes bedeutet. Passt euch also an, um alle mitzunehmen. Am Besten haltet ihr euren Kurs mit Pair-Programming – wobei es anders sicher auch gut funktioniert.

Begrüßung und Vorbereitung

~30 Min.

Begrüßt die Teilnehmenden am ersten Tag und macht eine Vorstellungsrunde. Vielleicht geht ihr hier besonders auf Vorerfahrung bei der Web-Programmierung ein. Erklärt dann den repl.it-Editor und zeigt ihnen, wie man ein Projekt erstellt.

Wenn ihr das gemacht habt, löscht die Counter-Komponente aus dem lib-Ordner, den assets-Ordner und den Code aus der App.svelte-Datei (das alles befindet sich im src-Ordner).
Geht dann auf die Grundstruktur des Projekts ein. Fokussiert euch dabei am besten auf index.html und App.svelte.

Die REPLs mit dem Beispielcode für Tag 1 findet ihr hier und hier.

Komponenten-Grundlagen

~30 Min.

Jetzt geht es richtig los. Zeigt den Teilnehmenden die Grundstruktur jeder Sveltekomponente.
Konkret könntet ihr sagen, dass jede Komponente eine eigene Datei ist und sie ein <script>-Tag, danach den HTML-Code und ein <style>-Tag haben. Schreibt dazu in App.svelte:

1
2
3
4
5
6
7
8
9

<script>

</script>

<p>Deine erste Svelte-Komponente!</p>

<style>

</style>

Gebt den Teilnehmenden jetzt die Aufgabe, die Grundstruktur in ihre App.svelte-Datei zu übernehmen und zusätzlich im <style>-Tag CSS hinzuzufügen, das den Text blau einfärbt. Sobald die Teilnehmenden das geschafft haben, kann es weitergehen. Sollten Probleme auftreten, zeigt ihnen, wie ihr es machen würdet. Eine Möglichkeit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11

<script>

</script>

<p>Deine erste Svelte-Komponente!</p>

<style> p { color: blue; }
</style>

Nun soll es darum gehen, eine komplett neue Komponente zu erstellen.
Zeigt den Teilnehmenden dazu, wie sie eine neue Datei im lib-Ordner erstellen können. Nennt eure Datei Name.svelte und schreibt folgenden Code:

1
2
3
4
5
6
7
8
9

<script>

</script>

<p>Mein Name ist Maja Musterfrau.</p>

<style>

</style>

Zeigt ihnen nun, wie sie diese Komponente in App.svelte einbinden können:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

<script> import Name from "./lib/Name.svelte";
</script>

<p>Deine erste Svelte-Komponente!</p>
<Name></Name>
<Name></Name>

<style> p { color: blue; }
</style>

Hier kommen nun mehrere interessante Eigenschaften von Svelte ans Licht; weist die Teilnehmenden auf die folgenden Dinge hin:

  • Komponenten werden mit normalem HTML eingefügt.
  • Komponenten können mehrfach eingefügt werden.
  • Komponentennamen werden als Konvention großgeschrieben, um sie nicht mit normalen HTML-Elementen zu verwechseln.
  • Obwohl das entsprechende CSS in App.svelte vorhanden ist, sind die Absätze innerhalb der Komponenten nicht blau. Das liegt daran, dass CSS, das innerhalb von Komponenten-Dateien definiert wird, nur für die Komponente selbst gilt (scoped CSS).

Gebt den Teilnehmenden die Aufgabe, eine neue Komponente für die Darstellung ihres Lieblingshobbys zu erstellen und in die App.svelte einzubinden. Steht ihnen wie immer helfend zur Seite :)


Parameter

~30 Min.

Jetzt haben wir zwar schon Komponenten, aber viel können sie noch nicht.
Im nächsten Schritt soll es also darum gehen, wie Parameter verwendet werden können.

Parameter innerhalb der Komponente hinzufügen

Geht dazu zum Beispiel der Namenskomponente zurück und fügt folgenden Code ein:

1
2
3
4
5
6
7
8
9

<script> export let name = "Maja Musterfrau";
</script>

<p>Mein Name ist { name }.</p>

<style>

</style>

Wichtig ist vor allem, zu erklären, dass das Wörtchen export dafür steht, dass die folgende Variable ein Parameter der Komponente sein soll. Ohne export könnten wir den Parameter im nächsten Schritt nicht von außen ansteuern.
Außerdem solltet ihr darauf eingehen, dass die geschweiften Klammern dafür stehen, dass an dieser Stelle der Wert des Parameters name und nicht der Text "name" eingefügt werden soll. Das ist für die Arbeit mit Svelte-Parametern (und generell Javascript-Ausdrücken) im HTML-Teil einer Komponente unabdingbar.


Parameter von außen ansteuern

Nun wollen wir die Parameter der Komponente von außen beeinflussen. Dazu gehen wir zur App.svelte und ändern den Code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

<script> import Name from "./lib/Name.svelte";
</script>

<p>Deine erste Svelte-Komponente!</p>
<Name></Name>
<Name name="Max Mustermann"></Name>

<style> p { color: blue; }
</style>

Das Ändern eines Parameters funktioniert also genauso wie das Vergeben von Attributen in normalem HTML. Weist die Teilnehmenden darauf hin, dass in der ersten Namenskomponente "Maja Musterfrau" steht, weil wir innerhalb der Komponente einen Standardwert für name vergeben haben, der also einfach übernommen wird.
Svelte ist hier relativ streng – wird kein Standardwert vergeben und die Komponente ohne die Zuweisung dieses Parameters eingebunden, gibt Svelte einen Fehler aus. Dementsprechend: Vergesst nicht, überall Standardwerte zu vergeben. Ist auch guter Stil :)
Die Teilnehmenden sollen nun mit dem neuen Wissen eine Liste ihrer Hobbys erstellen, indem sie der Hobby-Komponente einen Parameter geben und diesen dann in der App.svelte ansteuern.


Komponenten verschachteln

~15 Min.

In diesem Abschnitt soll das Ganze eine Stufe komplexer werden. Es soll nun eine kleine Steckbriefkomponente erstellt werden, die eine Namenskomponente, eine Alterskomponente und eine Adresskomponente enthält.
Bittet dazu die Teilnehmenden, eine Komponente für das Alter einer Person und eine für den Wohnort einer Person eigenständig zu erstellen. Sobald sie fertig sind, zeigt ihnen, wie man die Steckbriefkomponente erstellt, die alle erstellten Komponenten kombiniert:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18

<script> import Name from "./Name.svelte"; import Alter from "./Alter.svelte"; import Wohnort from "./Wohnort.svelte"; export let personName; export let personAlter; export let personWohnort;
</script>

<h2>Steckbrief</h2>
<Name name={personName}></Name>
<Alter alter={personAlter}></Alter>
<Wohnort wohnort={personWohnort}></Wohnort>

<style>

</style>

Die App.svelte sollte jetzt so aussehen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

<script> import Steckbrief from "./lib/Steckbrief.svelte";
</script>

<p>Deine erste Svelte-Komponente!</p>
<Steckbrief personName={"Maja Musterfrau"}
personAlter={14} personWohnort={"Hamburg"}></Steckbrief>

<style> p { color: blue; }
</style>

Hier sollen die Teilnehmenden vor allem verstehen, dass sich Parameter beliebig oft eine Ebene weiter geben lassen. Wenn ihnen das klar ist, haben sie eine gute Grundlage für die Projektarbeit am zweiten Tag.
An dieser Stelle ist es sicherlich auch mal Zeit für eine Pause :)
Gebt den Teilnehmenden – und euch ;) – am besten 30 Minuten zum Verschnaufen.


Events verarbeiten

~30 Min.

Nach der Pause ist ein guter Zeitpunkt, um ein neues Repl zu erstellen. Das ist natürlich nicht verpflichtend, aber deutlich übersichtlicher, als mit dem alten weiterzumachen.
Befolgt dabei dieselben Schritte wie am Anfang (assets-Ordner, Counter-Komponente und den Code aus App.svelte löschen) und fragt die Teilnehmenden anschließend, was ihr jetzt schreiben müsst, um die Grundstruktur für eine Komponente aufzubauen (<script> und <style>).

Jetzt soll es darum gehen, die Verarbeitung von events zu verstehen. Schreibt dazu folgenden Code (dieses Beispiel ist ja bei solchen Frameworks allgemein bekannt):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

<script> let klicks = 0; function geklickt() { klicks++; }
</script>

<button on:click={geklickt}>Ich wurde {klicks} mal angeklickt</button>

<style>

</style>

Erklärt den Code und geht dabei besonders auf Folgendes ein:

  • Alle möglichen Events können in Svelte mit einem on:eventname-Attribut angesteuert werden.
  • Zur Verarbeitung eines Events brauchen wir eine Javascript-Funktion, so wie die Teilnehmenden das vielleicht schon von herkömmlichen Event-Listenern kennen.
  • Theoretisch könnte man die Funktion auch direkt in das Attribut hineinschreiben (on:click={function() { klicks++; }}), aber das machen aus Übersichtlichkeitsgründen nicht.

Gebt den Teilnehmenden dann die Aufgabe, das nachzuprogrammieren und einen weiteren Button hinzuzufügen, der die Anzahl der Klicks auf den anderen Button bei einem Klick auf 0 zurücksetzt.
Gebt den Teilnehmenden hier Zeit, diese Aufgabe ist schon etwas anspruchsvoller.


Binding

~30 Min.

Wenn mit Texteingaben gearbeitet werden soll, interessiert uns, was die Benutzer eingeben. Schön wäre es hier besonders, wenn sich der Wert einer Variable in unserem Code direkt an die Eingaben anpassen kann. Dies ist in Svelte mit Binding möglich. Ziel soll es nun sein, eine Begrüßungskomponente zu erstellen, die den Namen einer Person abfragt und diese anschließend grüßt. Erstellt also eine "Gruss"-Komponente und schreibt folgenden Code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11

<script> export let name = "";
</script>

<p>Mein Name ist:</p>
<input bind:value={name}>
<p>Hallo {name}!</p>

<style>

</style>

Die Komponente muss dann natürlich noch in die App.svelte eingebunden werden:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

<script> import Gruss from "./lib/Gruss.svelte" let klicks = 0; function geklickt() { klicks++; }
</script>

<button on:click={geklickt}>Ich wurde {klicks} mal angeklickt</button>

<Gruss></Gruss>

<style>

</style>

Erklärt den Teilnehmenden, wie das Ganze im Hintergrund funktioniert:

  • Svelte erstellt im Hintergrund eine Funktion, die bei jedem input-Event ausgelöst wird.
  • Diese Funktion setzt dann den Wert der übergebenen Variable auf den Wert der Textbox.
  • Außerdem wird der Wert der Textbox jedes Mal an die Variable angepasst, wenn diese sich ändert.
  • So werden die beiden Werte aneinander "gebunden".

Erwähnt auch, dass es noch viele andere Fälle gibt, in denen Binding nützlich werden kann. Wenn beispielsweise in der Steckbriefkomponente von vor der Pause die Grusskomponente enthalten sein würde, müsste der Wert von personName der Steckbriefkomponente auch an den Wert von name der Grusskomponente gebunden werden, damit auch die Steckbriefkomponente immer den aktuellen Namen zur Verfügung hat.


Reaktive Statements

~30 Min.

Zum Schluss des Tages soll es noch um eine Sache gehen, die besonders wichtig für den zweiten Tag sein wird: Reaktive Statements.
Erklärt den Teilnehmenden, dass das Schreiben von $: im <script>-Tag einer Komponente anzeigt, dass Code, der jetzt kommt, auf Änderungen reagieren soll. So lässt sich bspw. eine Namenskomponente Name.svelte erstellen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

<script> export let vorname = ""; export let nachname = ""; function logRueckwaerts(str) { console.log(str.split("").reverse().join("")); } $: name = vorname + " " + nachname; $: if(nachname.length > 10) { console.log("Ganz schön langer Nachname!") } $: { console.log(vorname.length); console.log(nachname.length); } $: logRueckwaerts(vorname);
</script>

<p>Vorname: <input bind:value={vorname}/></p>
<p>Nachname: <input bind:value={nachname}/></p>
<p>Hallo {name}!</p>

<style>

</style>

Die Einbindung erfolgt wie gewohnt. Schreibt die 4 reaktiven Ausdrücke am besten nacheinander hin und erklärt jeden Ausdruck einzeln:

  • Eine reaktive Variable kann so erstellt werden. Hier müssen wir nicht einmal let schreiben. Die Variable wird immer dann neu zugewiesen, wenn sich irgendeine der in der Zuweisung vorkommenden Variablen ändert.
  • Auch if-Abfragen können reaktiv gemacht werden. Sie werden immer dann ausgeführt, wenn sich die Variable(n) in der Abfrage ändert.
  • Geschweifte Klammern zeigen an, dass der Code in den Klammern immer dann neu ausgeführt werden soll, wenn sich irgendeine in den Klammern vorkommende Variable ändert.
  • Auch eine Funktion kann immer dann ausgeführt werden, wenn einer der übergebenen Parameter sich ändert.

Lasst die Teilnehmenden damit ein bisschen herumprobieren, wenn noch Zeit dafür da ist. Sobald einige nichts mehr zu tun haben, könnt ihr entweder die Teilnehmenden für den Tag entlassen und verabschieden (wenn keine Zeit mehr ist), oder mit ihnen noch das folgende Extrathema durcharbeiten.


Bedingtes HTML

~15 Min.

In Svelte können wir aufgrund von Bedingungen unterschiedliches HTML anzeigen. Zeigt gen Teilnehmenden das mit diesem Code (in einer Status-Komponente):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

<script> export let status = "";
</script> {#if status != ""} <p>Im Moment ist der Status so: {status}</p> {:else} <p>Im Moment gibt es keinen Status.</p> {/if} <style>

</style>

Bindet die Komponente entsprechend ein und vergebt verschiedene Werte für status. Erklärt dann die Syntax für die Bedingungen:

  • Ein Befehl im HTML wird immer mit einem # begonnen. Dann folgt der Befehlsname (hier if).
  • Wenn ein Befehl weitergeführt wird, schreibt man : und dann den Befehlsnamen (hier else, aber auch else if würde funktionieren).
  • Jeder Befehl wird mit / + Befehlsname (hier wieder if) abgeschlossen.

Spätestens jetzt seid ihr für heute fertig. Wünscht den Teilnehmenden einen schönen Tag/Abend – hoffentlich nicht mehr vor dem PC ;)


Projektarbeit: Energienetzwerk

~3,5 Std.

Den Startcode für die Projektarbeit findet ihr hier. Ein fertiges Projekt könnte (mit etwas mehr als den zur Verfügung stehenden 3,5 Stunden) so aussehen.
Am zweiten Tag soll alles ein bisschen freier werden, damit sich die Teilnehmenden mit Svelte austoben können. Dazu soll eine Projektarbeit gemacht werden, in der ein Energienetzwerk simuliert werden soll. Dazu gibt es ein bisschen Startcode, damit die Teilnehmenden kein leeres Projekt vor sich haben, sondern schon auf etwas aufbauen können.
Fangt aber erstmal damit an, die Teilnehmenden zu begrüßen und vielleicht einen kurzen Energizer zu machen. Fragt sie dann, wo der Strom aus ihrer Steckdose eigentlich herkommt. Ihr könnt auch anschließend noch fragen, was die Teilnehmenden denn für Kraftwerksarten kennen. Sobald ihr ein bisschen gesammelt habt, leitet die Projektarbeit ein und zeigt den Teilnehmenden folgenden Beispielcode für ein Windrad:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21

<script> export let zeit = 0; export let generiert = function (energie) { }; function erzeugen(zeit) { generiert(1); } $: erzeugen(zeit);
</script>

<div class="windrad">

</div>

<style>

</style>

Erklärt den Teilnehmenden, dass jedes Mal, wenn die Zeit voranschreitet, die definierte Funktion aufgerufen und so Energie erzeugt wird. Erklärt ihnen dann, dass die generiert-Funktion dazu da ist, dass eine Komponente, die das Windrad einbindet, auch auf die erzeugte Energie reagieren kann. Zeigt ihnen dann den Code für die App.svelte, um das Gesagte zu verdeutlichen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

<script> import Windrad from "./lib/Windrad.svelte"; let energie = 0; function energieErhalten(neueEnergie) { energie += neueEnergie; }
</script>

<Windrad generiert={energieErhalten}></Windrad>

<p>Insgesamt wurde {energie} Energie generiert.</p>

<style>

</style>

Die App.svelte bindet also an den energie-Parameter der Windradkomponente, um die erzeugte Energie zu erfassen. Jetzt fehlt nur noch eine Zeitkomponente, die die Zeit vorwärts laufen lässt. Der Code dafür ist:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11

<script> export let zeit = 0; let intervall = setInterval(() => { zeit++; }, 1000);
</script>

<style>

</style>

Geht beim Erklären besonders auf setInterval ein. Manche könnten die schon kennen, aber einige sicherlich auch nicht. Mit der Einbindung der Zeitkomponente sieht der App.svelte-Code so aus:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20

<script> import Windrad from "./lib/Windrad.svelte"; import Zeit from "./lib/Zeit.svelte"; let zeit = 0; let energie = 0; function energieErhalten(neueEnergie) { energie += neueEnergie; }
</script>

<Windrad zeit={zeit} generiert={energieErhalten}></Windrad>
<Zeit bind:zeit={zeit}></Zeit>

<p>Insgesamt wurde {energie} Energie generiert.</p>

<style>

</style>

Führt das Projekt nun aus. Es sollte zu sehen sein, dass sich die Energie jede Sekunde erhöht.

Jetzt sollen die Teilnehmenden selbst ran. Zeigt ihnen jetzt noch die möglichen Richtungen auf, in die sie weiterdenken und -programmieren können:

  • Lässt sich ein Windrad auch grafisch darstellen? (Weist die Teilnehmenden auf die zur Verfügung stehenden Grafiken hin.)
  • Könnte man auch die Windstärke simulieren?
  • Was ist mit anderen Kraftwerksformen?
  • Der Stromverbrauch bei den Haushalten ist nicht zu jeder Tageszeit gleich. Lässt sich das einbeziehen?
  • Könnte man eine Komponente bauen, die den Strom misst, damit man die in jedes Kraftwerk einbinden kann?
  • Gibt es Zwischenspeicher, um ungenutzten Strom nicht zu verschwenden?
  • Sollen die Kraftwerke realistisch sein? Wie lässt sich die in Wahrheit pro Stunde generierte Energie eines Kraftwerks herausfinden? (Verweist die Teilnehmenden an Wikipedia.)
  • Lässt sich das Ganze zu einer schönen Website ausgestalten?

Ab hier liegt es an den Teilnehmenden, wie es weitergeht. Steht ihnen helfend zur Seite (bedenkt dabei, dass am Tag davor ihr erster Kontakt mit Svelte war) und zeigt ihnen auch neue Dinge, wenn ihr das für sinnvoll haltet.


Abschlussrunde und Feedback

~30 Min.

Trefft euch am Ende des Tages noch für eine halbe Stunde, um genug Zeit für Abschlussrunde und Feedback zu haben. Lasst die Teilnehmenden, die wollen, ihre Projekte vorstellen.
Holt euch dann ein kurzes Feedback von den Teilnehmenden ein. Wenn ihr all das gemacht habt, ist es auch schon Zeit, sich zu verabschieden. Dankt den Teilnehmenden für ihre ausdauernde Mitarbeit, zeigt ihnen weitere Anlaufstellen für Svelte (die Tutorialseite und die Dokumentation von Svelte, oder auch Videotutorials auf Youtube) und Programmieren generell (Übersicht der Hacker School) und wünscht ihnen weiterhin alles Gute.


Anhang

Hier findet ihr Grafiken, die ihr den Teilnehmenden für die Projektarbeit zur Verfügung stellen könnt. Die Grafiken sind für die Erstellung eines Windrads, eines Solarpanels und eines Strommessgeräts geeignet.