Etwas weniger magisch, aber leichter zu lernen
Feine Syntax und Event-Handling: die neuen Features in Svelte 5
Von: Nils Röhrig
Die Welt der JavaScript-basierten UI-Frameworks ist so bunt und vielschichtig wie das gesamte JavaScript-Ökosystem. Neben den Platzhirschen React, Angular und Vue haben sich auch andere Werkzeuge einen Namen gemacht. Eines dieser Werkzeuge ist Svelte, das ursprünglich bereits 2016 veröffentlicht wurde.
Zum Durchbruch kam es jedoch erst 2019 mit Version 3. Seitdem ist Svelte fester Bestandteil des breiteren Web-Frontend-Diskurses und erreicht in Zufriedenheitsumfragen stets hohe Platzierungen. Ende Oktober 2024 ist nun Version 5 erschienen, die weitreichende Änderungen in Syntax und Features einführt. Egal ob du bereits mit Svelte gearbeitet hast oder das Framework dir komplett neu ist: In diesem Artikel möchte ich dir Svelte und die neuen Features näherbringen.
Sveltes Kerneigenschaften
Wie bereits erwähnt, ist Svelte ein JavaScript-basiertes UI-Komponenten-Framework. Das heißt, du benutzt es, um Benutzeroberflächen für Websites und Web-Apps zu entwickeln. Anders als die meisten anderen Frameworks setzt Svelte einen Compiler ein und kann ohne auch gar nicht benutzt werden. Für dich bedeutet das, dass deine Svelte-Komponenten in einer eigenen Sprache geschrieben und dann vom Compiler in kompakte, hochoptimierte JavaScript-Module übersetzt werden, die du dann auf deinen Websites und Web-Apps verwenden kannst.
Wenn dich die erwähnte „eigene Sprache“ abgeschreckt hat, so lass mich dich gleich wieder beruhigen. Die Svelte-Syntax verfolgt nämlich den HTML-first-Ansatz. Das heißt, Svelte-Code ist im Kern HTML-Code, der durch ein paar sinnvolle Erweiterungen ergänzt wird. Svelte-Komponenten sind üblicherweise wie in diesem Beispiel zur Komponentenstruktur aufgebaut:
<script>
// Zustand und Verhalten
</script>
<!-- Komponenten-Markup -->
<style>
/* Komponenten-Stile */
</style>
Das Beispiel zeigt die Bestandteile einer Svelte-Komponente und welchen Zweck sie jeweils haben. Wie du siehst, sind Svelte-Komponenten wie traditionelle Websites aufgebaut. Sie bestehen aus dem <script>
-Block, dem <style>
-Block sowie dem übrigen Markup der Komponente.
Logikblöcke
Bei Logikblöcken handelt es sich um eine der Spracherweiterungen von Svelte. Mit ihnen kannst du innerhalb deines Komponenten-Markups kontrollieren, welches HTML unter welchen Bedingungen generiert wird. Das ist nützlich, wenn bestimmte Teile des HTMLs nur unter bestimmten Bedingungen angezeigt werden sollen. Es ist auch hilfreich, wenn du eine Liste von Dingen hast und du für jedes Ding ein bisschen gleichförmiges HTML ausgeben möchtest. Im folgenden Beispiel zu Logikblöcken zeige ich dir, wie das aussieht:
<script>
let fruits = $state(["apple", "banana", "kiwi"]);
</script>
{#if fruits.length}
<p>Die Liste hält {fruits.length} Früchte.</p>
{/if}
{#each fruits as fruit}
<p>{fruit}</p>
{/each}
Wie du siehst, erinnern Logikblöcke zum einen an Kontrollstrukturen in anderen Programmiersprachen. Zum anderen erinnern sie aber auch an klassische Template-Sprachen wie beispielsweise Handlebars. So erlaubt der {#if}
-Block die bedingte Darstellung von Markup abhängig vom Wert des Ausdrucks. Der {#each}
-Block ermöglicht es dir, eine Liste von Daten zu durchlaufen und für jedes Element eine Ausgabe zu machen. Das macht Svelte-Syntax für Entwickler:innen aller Couleur sehr einfach zu lesen.
Dir sind sicher sowohl das Wörtchen $state
im <script>
-Block, als auch die Verwendung von geschwungenen Klammern im Markup aufgefallen. Über Ersteres spreche ich weiter unten. Letzteres ist der Weg, wie du dynamische Daten in deinem Markup ausgeben kannst. Innerhalb der Klammern kann nämlich jeder beliebige JavaScript-Ausdruck stehen, Statements sind hingegen nicht erlaubt.
Direktiven
Eine weitere Syntax-Erweiterung sind Direktiven. Du kannst sie nutzen, um bestimmte Verhaltensweisen mit HTML-Elementen oder im Markup genutzten Svelte-Komponenten zu verknüpfen. Hier ist ein Beispiel zur Verwendung der bind:
-Direktive:
<script>
let value = $state("Hallo Heise Academy!")
</script>
Wert eingeben: <input bind:value><br>
Eingegebener Wert: <output>{value}</output>
Direktiven verwendest du wie HTML-Attribute und sie enthalten immer einen Doppelpunkt zur Unterscheidung. Die bind:
-Direktive ermöglicht es dir, ein Eingabefeld über Zwei-Wege-Datenbindung mit einer Zustandsvariable zu verknüpfen. Das bedeutet, dass Änderungen am Wert der Variable im Eingabefeld und Änderungen im Eingabefeld im Wert der Variable reflektiert werden. Prinzipiell lässt sich diese Mechanik an mehreren Stellen verwenden. Ich empfehle dir aber, dass du Zwei-Wege-Datenbindung nur im Zusammenhang mit Formularelementen nutzt. Aus eigener Erfahung weiß ich, dass es andernfalls sehr schwierig werden kann, dem Applikations-Code zu folgen.
Runen
Eine der wichtigsten Syntax-Erweiterungen in Svelte sind Runen, denn sie ermöglichen dir die Arbeit mit reaktiven Werten. Reaktivität bedeutet hier, dass deine Benutzeroberfläche auf Änderungen deines Programmzustands reagiert. Änderungen am Zustand werden dort also unmittelbar reflektiert. Runen kannst du dir dabei als Schlüsselwörter vorstellen, die dem Svelte-Compiler spezielle Anweisungen mitgeben. Sie sind genauso Teil der Sprache, wie es Logikblöcke sind. Du kannst Runen sogar außerhalb deiner Svelte-Komponenten überall in deiner Code-Basis verwenden. Die einzige Bedingung ist, dass der Dateiname mit .svelte.js
oder .svelte.ts
endet. Nur so weiß der Svelte-Compiler, welche Dateien er berücksichtigen muss.
Die wichtigse Rune hast du schon gesehen. Sie heißt $state()
und du verwendest sie zur Deklaration einer reaktiven Zustandsvariable. Hier ist ein Beispiel für einen simplen Zähler, der von dieser Rune Gebrauch macht:
Wie du sehen kannst, wird hier eine reaktive Zustandsvariable namens count
deklariert und mit dem Startwert 0
versehen. Daneben sind zwei Funktionen definiert, die diesen Wert jeweils erhöhen oder absenken. Beide Funktionen sind mit Buttons verknüpft, die sie auslösen. Die Verarbeitung von Events erläutere ich weiter unten ausführlicher. Am wichtigsten ist hier die Erkenntnis, dass deine Änderungen an der Zustandsvariablen unmittelbar im UI reflektiert werden. Das nimmt Svelte dir ab, du brauchst dich darum nicht zu kümmern.
Es gibt noch weitere Runen, wie $derived()
, $effect()
oder $props()
, die ich in diesem Artikel aus Gründen der Verständlichkeit nicht näher beleuchte. Stattdessen möchte ich dir noch etwas zum Event-Handling erzählen.
Event-Handling
Wie du Event-Listener auf Elementen registrierst, hast du schon im letzten Beispiel gesehen. Generell funktioniert dieser Ansatz bei HTML-Elementen mit allen DOM-Events, die das Zielelement produzieren kann. Bei einem Formular ist das beispielsweise onsubmit
oder bei Eingabefeldern oninput
. Die jeweils zugewiesenen Werte sind einfache Callback-Funktionen, die von Svelte aufgerufen werden, sobald das entsprechende Event eintritt. Im folgenden Beispiel zum Event-Handling wird das nochmal deutlich:
<script>
function onclick() { console.log("Button geklickt.") }
function submitForm(e) {
e.preventDefault();
console.log("Formular abgeschickt.");
}
</script>
<form onsubmit={submitForm} method="post">
<input name="some-input" placeholder="Gib einen Wert ein">
<button type="submit" {onclick}>Abschicken</button>
</form>
Im Beispiel werden zwei Funktionen definiert und mit den jeweiligen Events verknüpft. Du kannst zwei verschiedene Wege sehen: den regulären Weg bei onsubmit
und den Shorthand-Weg bei onclick
. Letzterer ist immer dann möglich, wenn die zu verknüpfende Variable oder Funktion denselben Namen trägt, wie das Attribut des Zielelements. Das funktioniert im Übrigen für alle HTML-Attribute, nicht nur für Event-Listener.
Fazit
Neben den genannten Features hat Svelte natürlich noch eine Menge mehr zu bieten. Doch Änderungen wie Runen und die neue Art, Events zu handeln, sprechen in meinen Augen für sich. Svelte ist zwar nun etwas weniger magisch aber dafür einfacher zu lernen, nachvollziehbarer, zuverlässiger und schneller. Eigenschaften, die für neue Major-Versionen von Software nicht selbstverständlich sind. Falls du Svelte bislang noch nicht verwendet hast, so hoffe ich, dass deine Neugier nun geweckt ist. Und falls du Svelte in der Vergangenheit bereits verwendet hast, konnte mein Artikel dir bestimmt einen hilfreichen Überblick über einige der Änderungen geben.
Über den Autor: Nils Röhrig
Nils Röhrig ist Softwareentwickler, Redner und Trainer, der sich auf Frontend-Entwicklung mit dem Schwerpunkt Svelte spezialisiert hat. Er begann seine Karriere als Technical Consultant bei Questback, bevor er 2016 zu REWE digital wechselte. Dort war er an der Entwicklung und Pflege der hauseigenen E-Commerce-Plattform für den Liefer- und Abholservice beteiligt. Im Jahr 2022 wechselte Nils zu Loql, wo er an einer B2B-App arbeitet, die lokale und regionale Lebensmittelproduzenten mit ihren Kunden verbindet.