Eigene Komponenten
Aufbau einer Astro-Komponente
Abschnitt betitelt „Aufbau einer Astro-Komponente“Eine Datei .astro hat zwei Teile: oben zwischen --- JavaScript, das beim Build läuft, unten HTML-ähnliches Markup. Die einfachste Komponente dieser Plattform ist Lernziele:
---import { Aside } from '@astrojs/starlight/components';---
<Aside type="tip" title="Lernziele"> <slot /></Aside><slot /> ist der Platzhalter für das, was zwischen Öffnungs- und Schliess-Tag steht. In MDX:
import Lernziele from '@components/Lernziele.astro';
<Lernziele>- Du kannst ...- Du verstehst ...</Lernziele>Der Nutzen: Wenn du später alle Lernziel-Kästen anders aussehen lassen willst, änderst du eine Datei statt vierzig Seiten.
Mit Props gibst du einer Komponente Werte mit. Aufgabe bekommt einen Titel:
---import { Aside } from '@astrojs/starlight/components';interface Props { titel: string;}const { titel } = Astro.props;---
<Aside type="note" title={`Aufgabe ${titel}`}> <slot /></Aside>Das interface Props ist TypeScript und sorgt dafür, dass der Editor meckert, wenn titel fehlt. Astro.props enthält die übergebenen Werte. In MDX: <Aufgabe titel="3.1 · Rechte setzen">...</Aufgabe>.
HTML und CSS ohne JavaScript
Abschnitt betitelt „HTML und CSS ohne JavaScript“Loesung ist ein eingeklappter Bereich. Dafür braucht es kein JavaScript, HTML kann das mit <details>:
---interface Props { titel?: string;}const { titel = 'Lösung anzeigen' } = Astro.props;---
<details class="loesung"> <summary>{titel}</summary> <slot /></details>Das Fragezeichen in titel? macht die Prop optional, der Standardwert steht in der Zuweisung. Das Aussehen kommt aus src/styles/custom.css (nächste Seite).
Mit JavaScript: das Quiz
Abschnitt betitelt „Mit JavaScript: das Quiz“Der Selbstcheck muss im Browser reagieren, wenn jemand «Antworten prüfen» klickt. Dafür hat die Komponente ein <script>-Element. Astro bündelt es und liefert es nur auf Seiten aus, die das Quiz verwenden.
---interface Frage { frage: string; antworten: string[]; richtig: number | number[]; erklaerung?: string;}interface Props { fragen: Frage[];}const { fragen } = Astro.props;---
<div class="quiz" data-quiz> {fragen.map((f, i) => ( <fieldset data-richtig={[f.richtig].flat().join(',')}> <legend>{i + 1}. {f.frage}</legend> {f.antworten.map((a, j) => ( <label><input type="radio" name={`f${i}`} value={j} /> {a}</label> ))} </fieldset> ))} <button type="button" data-check>Antworten prüfen</button></div>
<script> document.querySelectorAll('[data-quiz]').forEach((quiz) => { quiz.querySelector('[data-check]')?.addEventListener('click', () => { quiz.querySelectorAll('fieldset').forEach((fs) => { const gewaehlt = Array.from(fs.querySelectorAll('input:checked')).map((i) => i.value).join(','); fs.classList.toggle('correct', gewaehlt === fs.dataset.richtig); }); }); });</script>Zwei Dinge sind hier wichtig. Erstens: Der obere Teil und das Markup laufen beim Build und erzeugen fertiges HTML, die Fragen stehen also im HTML der Seite. Zweitens: Nur das <script> läuft im Browser. Es darf nicht auf fragen zugreifen, diese Variable existiert dort nicht. Darum stehen die richtigen Antworten als data-richtig im HTML.
Die vollständige Komponente mit Mehrfachauswahl, Erklärungen und Punktestand liegt im Repository dieser Plattform unter src/components/Quiz.astro.
Import-Alias
Abschnitt betitelt „Import-Alias“Ein Import wie ../../../components/Quiz.astro hängt von der Ordnertiefe ab und bricht beim Verschieben einer Seite. Ein Alias löst das:
{ "extends": "astro/tsconfigs/strict", "compilerOptions": { "baseUrl": ".", "paths": { "@components/*": ["src/components/*"] } }}Danach gilt überall import Quiz from '@components/Quiz.astro';. Astro liest die paths aus tsconfig.json und löst sie beim Build auf.
- Ordner
src/components/anlegen undLernziele.astro,Aufgabe.astro,Loesung.astrowie oben erstellen. - Alias in
tsconfig.jsoneintragen, Dev-Server neu starten (Alias-Änderungen werden nicht live übernommen). - In
01-hallo.mdxdie drei Komponenten einsetzen.
Lösung anzeigen
---interface Props { titel?: string;}const { titel = 'Merke' } = Astro.props;---
<blockquote class="merksatz"> <strong>{titel}:</strong> <slot /></blockquote>Selbstcheck · 3 Fragen