Zum Inhalt springen

Komponenten

Astro-Komponenten sind die Grundbausteine eines jeden Astro-Projekts. Sie sind reine HTML-Vorlagen ohne clientseitigen Laufzeit-Code.

Die Astro-Komponentensyntax ist eine Obermenge von HTML. Die Syntax wurde so konzipiert, dass sie jedem vertraut ist, der Erfahrung mit dem Schreiben von HTML oder JSX hat und bietet Unterstützung für die Verwendung von Komponenten und JavaScript-Ausdrücken. Du erkennst eine Astro-Komponente an ihrer Dateierweiterung: .astro.

Astro-Komponenten sind extrem flexibel. Oft enthält eine Astro-Komponente eine wiederverwendbare Benutzeroberfläche der Seite, wie z. B. eine Kopfzeile oder eine Profilkarte. In anderen Fällen kann eine Astro-Komponente einen kleineren HTML-Schnipsel enthalten, z. B. eine Sammlung üblicher <meta>-Tags, die die Suchmaschinenoptimierung erleichtern. Astro-Komponenten können sogar ein ganzes Seitenlayout enthalten.

Das Wichtigste an Astro-Komponenten ist, dass sie während des Build-Prozesses zu HTML rendern. Selbst wenn du JavaScript-Code in deinen Komponenten ausführst, wird dieser vorzeitig ausgeführt und von der endgültigen Seite, die an deine Nutzerinnen und Nutzer gesendet wird, entfernt. Das Ergebnis ist eine schnellere Seite, welche standardmäßig kein JavaScript enthält.

Eine Astro-Komponente besteht aus zwei Hauptteilen: dem Komponentenskript und der Komponentenvorlage. Jeder Teil erfüllt eine andere Aufgabe, aber zusammen sollen sie ein Gerüst bieten, das sowohl einfach zu benutzen als auch ausdrucksstark genug ist, um alles zu handhaben, was du bauen möchtest.

---
// Komponentenskript (JavaScript)
---
<!-- Komponentenvorlage (HTML- + JS-Ausdrücke) -->

Du kannst Komponenten innerhalb anderer Komponenten verwenden, um mehr und fortschrittlichere Benutzeroberflächen zu erstellen. Zum Beispiel könnte eine Button-Komponente verwendet werden, um eine ButtonGroup-Komponente wie folgt zu erstellen:

ButtonGroup.astro
---
import Button from './Button.astro';
---
<div>
<Button title="Button 1" />
<Button title="Button 2" />
<Button title="Button 3" />
</div>

Astro verwendet einen Code Fence (---), um das Komponentenskript in deiner Astro-Komponente zu identifizieren. Wenn du schon einmal Markdown geschrieben hast, kennst du vielleicht ein ähnliches Konzept, das Frontmatter genannt wird. Astros Idee eines Komponentenskripts wurde direkt von diesem Konzept inspiriert.

Du kannst das Komponentenskript verwenden, um jeden JavaScript-Code zu schreiben, den du zum Rendern deiner Vorlage benötigst. Dies kann Folgendes beinhalten:

  • Importieren anderer Astro-Komponenten
  • Importieren anderer Framework-Komponenten, wie z. B. React
  • Importieren von Daten, wie z. B. einer JSON-Datei
  • Abruf von Inhalten aus einer API oder Datenbank
  • Erstellen von Variablen, auf die du in deiner Vorlage verweisen wirst
---
// Hinweis: Die Importe müssen am Anfang der Datei stehen.
import SomeAstroComponent from '../components/SomeAstroComponent.astro';
import SomeReactComponent from '../components/SomeReactComponent.jsx';
import someData from '../data/pokemon.json';
// Zugriff auf übergebene Komponenteneigenschaften, wie z.B. `<X title="Hallo, Welt!" />`
const {title} = Astro.props;
// Abrufen externer Daten, auch aus einer privaten API oder Datenbank
const data = await fetch('EINE_GEHEIME_API_URL/users').then(r => r.json());
---
<!-- Deine Vorlage hier! -->

Der Code Fence soll garantieren, dass das von dir geschriebene JavaScript “eingezäunt” ist. Es wird nicht in deine Frontend-Anwendung entkommen oder in die Hände deiner Nutzerinnen und Nutzer fallen. Du kannst hier sicher Code schreiben, der teuer oder sensibel ist (z. B. eine Anfrage an deine private Datenbank), ohne dir Sorgen zu machen, dass er jemals im Browser landet.

Unterhalb des Komponentenskripts befindet sich die Komponentenvorlage. Die Komponentenvorlage bestimmt die HTML-Ausgabe deiner Komponente.

Wenn du hier einfaches HTML schreibst, wird deine Komponente dieses HTML in jeder Astro-Seite darstellen, die sie importiert und verwendet.

Die Syntax der Astro-Komponentenvorlagen unterstützt jedoch auch JavaScript-Ausdrücke, importierte Komponenten und spezielle Astro-Direktiven. Daten und Werte, die (zur Zeit der Seitenerstellung) im Komponentenskript definiert werden, können in der Komponentenvorlage verwendet werden, um dynamisch erstelltes HTML zu erzeugen.

---
// Dein Komponentenskript hier!
import ReactPokemonComponent from '../components/ReactPokemonComponent.jsx';
const myFavoritePokemon = [/* ... */];
---
<!-- HTML-Kommentare werden unterstützt! -->
<h1>Hallo, Welt!</h1>
<!-- Verwende Eigenschaften und andere Variablen aus dem Komponentenskript: -->
<p>Mein Lieblingspokemon ist: {Astro.props.title}</p>
<!-- Einbindung anderer Komponenten mit einer "client:"-Anweisung zur Hydratisierung: -->
<ReactPokemonComponent client:visible />
<!-- Mische HTML mit JavaScript-Ausdrücken, ähnlich wie bei JSX: -->
<ul>
{myFavoritePokemon.map((data) => <li>{data.name}</li>)}
<ul>
<!-- Verwende eine Vorlagendirektive, um eine unescapte HTML-Zeichenkette in ein Element einzufügen: -->
<p set:html={rawHTMLString} />

Du kannst lokale Variablen innerhalb des Frontmatter-Komponentenskripts einer Astro-Komponente definieren. Diese Variablen können dann unter Verwendung von JSX-Ausdrücken in die HTML-Vorlage der Komponente eingefügt werden.

Lokale Variablen können zum HTML-Code hinzugefügt werden, indem der Variablenname in geschweifte Klammern gesetzt wird:

---
const name = "Astro";
---
<div>
<h1>Hallo {name}!</h1> <!-- Ausgabe: <h1>Hallo Astro!</h1> -->
</div>

Lokale Variablen können in geschweiften Klammern verwendet werden, um Attributwerte sowohl an HTML-Elemente als auch an Komponenten zu übergeben:

---
const name = "Astro";
---
<h1 class={name}>Attributausdrücke werden unterstützt</h1>
<MyComponent templateLiteralNameAttribute={`MeinNameIst${name}`} />

Lokale Variablen können in JSX-ähnlichen Funktionen verwendet werden, um dynamisch generierte HTML-Elemente zu erzeugen:

---
const items = ["Hunde", "Katzen", "Schnabeltiere"];
---
<ul>
{items.map((item) => (
<li>{item}</li>
))}
</ul>

Im Gegensatz zu JavaScript oder JSX kann eine Astro-Komponentenvorlage mehrere Elemente darstellen, ohne dass alles in ein einziges <div> oder <> verpackt werden muss.

---
// Vorlage mit mehreren Elementen
---
<p>Es ist nicht erforderlich, Elemente in einen einzelnen Container zu verpacken.</p>
<p>Astro unterstützt mehrere Stammelemente in einer Vorlage.</p>

Wenn du jedoch einen Ausdruck verwendest, um dynamisch Elemente zu erstellen, solltest du diese mehreren Elemente mit einem Fragment umhüllen, genau wie du es in JavaScript oder JSX tun würdest. In Astro kannst du dazu entweder <Fragment> </Fragment> oder die Kurzform <> </> verwenden.

---
const items = ["Hunde", "Katzen", "Schnabeltiere"];
---
<ul>
{items.map((item) => (
<>
<li>Rote {item}</li>
<li>Blaue {item}</li>
<li>Grüne {item}</li>
</>
))}
</ul>

Fragmente können auch nützlich sein, um Container-Elemente bei der Verwendung von set:*-Direktiven zu vermeiden, so wie im folgenden Beispiel:

---
const htmlString = '<p>Roher HTML-Inhalt</p>';
---
<Fragment set:html={htmlString} />

Eine Astro-Komponente kann Eigenschaften definieren und akzeptieren. Diese Eigenschaften stehen dann der Komponentenvorlage für die Darstellung von HTML zur Verfügung. Eigenschaften sind im globalen Objekt Astro.props in deinem Frontmatter-Skript verfügbar.

Hier ist ein Beispiel für eine Komponente, die die Eigenschaften greeting und name empfängt. Beachte, dass die zu empfangenden Eigenschaften aus dem globalen Objekt Astro.props destrukturiert werden.

GreetingHeadline.astro
---
// Verwendung: <GreetingHeadline greeting="Guten Tag" name="Partner" />
const { greeting, name } = Astro.props
---
<h2>{greeting}, {name}!</h2>

Du kannst deine Eigenschaften auch mit TypeScript definieren, indem du ein Typ-Interface Props exportierst. Astro übernimmt automatisch jedes exportierte Props-Interface und gibt Typ-Warnungen/Fehler für dein Projekt aus. Diese Eigenschaften können auch mit Standardwerten versehen werden, wenn sie aus Astro.props destrukturiert werden.

src/components/GreetingHeadline.astro
---
export interface Props {
name: string;
greeting?: string;
}
const { greeting = "Hallo", name } = Astro.props as Props;
---
<h2>{greeting}, {name}!</h2>

Wenn diese Komponente importiert und in anderen Astro-Komponenten, Layouts oder Seiten gerendert wird, können diese Eigenschaften als Attribute übergeben werden:

src/components/GreetingCard.astro
---
import GreetingHeadline from './GreetingHeadline.astro';
const name = "Astro"
---
<h1>Grußkarte</h1>
<GreetingHeadline greeting="Hey" name={name} />
<p>Ich hoffe, du hast einen schönen Tag!</p>

Das <slot />-Element ist ein Platzhalter für externe HTML-Inhalte, der es dir ermöglicht, untergeordnete Elemente aus anderen Dateien in deine Komponentenvorlage einzubinden.

Standardmäßig werden alle untergeordneten Elemente, die an eine Komponente übergeben werden, in ihrem <slot /> gerendert.

src/components/Wrapper.astro
---
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';
const { title } = Astro.props
---
<div id="content-wrapper">
<Header />
<Logo />
<h1>{title}</h1>
<slot /> <!-- Untergeordnete Elemente werden hier angezeigt -->
<Footer />
</div>
src/pages/fred.astro
---
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="Freds Seite">
<h2>Alles über Fred</h2>
<p>Hier findest du einige Informationen über Fred.</p>
</Wrapper>

Dieses Muster ist die Grundlage einer Astro-Layout-Komponente: Eine ganze Seite mit HTML-Inhalt kann mit <Layout></Layout>-Tags „umhüllt“ und an die Layout-Komponente gesendet werden, um innerhalb der allgemeinen Seitenelemente gerendert zu werden.

Eine Astro-Komponente kann auch benannte Slots haben. Dadurch kannst du nur HTML-Elemente mit dem entsprechenden Slot-Namen an die Position eines Slots übergeben.

src/components/Wrapper.astro
---
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';
const { title } = Astro.props
---
<div id="content-wrapper">
<Header />
<slot name="after-header"/> <!-- Untergeordnete Elemente mit dem `slot="after-header"`-Attribut werden hier angezeigt -->
<Logo />
<h1>{title}</h1>
<slot /> <!-- Untergeordnete Elemente ohne `slot`, oder mit `slot="default"`-Attribut werden hier angezeigt -->
<Footer />
<slot name="after-footer"/> <!-- Untergeordnete Elemente mit dem `slot="after-footer"`-Attribut werden hier angezeigt -->
</div>
src/pages/fred.astro
---
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="Freds Seite">
<img src="https://my.photo/fred.jpg" slot="after-header">
<h2>Alles über Fred</h2>
<p>Hier findest du einige Informationen über Fred.</p>
<p slot="after-footer">Copyright 2022</p>
</Wrapper>

Verwende ein slot="my-slot"-Attribut auf dem untergeordneten Element, das du an einen passenden <slot name="my-slot" />-Platzhalter in deiner Komponente weiterleiten willst.

Slots können auch Fallback-Inhalte wiedergeben. Wenn es keine passenden untergeordneten Elemente gibt, die an einen Slot übergeben werden, wird ein <slot /> Element seine eigenen Platzhalter-Elemente anzeigen.

src/components/Wrapper.astro
---
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';
const { title } = Astro.props
---
<div id="content-wrapper">
<Header />
<Logo />
<h1>{title}</h1>
<slot>
<p>Dies ist mein Fallback-Inhalt, wenn kein Element
an diesen Slot übergeben wird.</p>
</slot>
<Footer />
</div>

Die Einbindung von CSS-Stilen über <style>-Tags wird auch innerhalb der Komponentenvorlage unterstützt.

Sie können zur Gestaltung deiner Komponenten verwendet werden. Alle Stilregeln werden automatisch auf die Komponente selbst beschränkt, um CSS-Konflikte in großen Anwendungen zu vermeiden.

---
// Dein Komponentenskript hier!
---
<style>
/* Beschränkt auf diese Komponente, andere H1s
auf der Seite bleiben unverändert */
h1 { color: red }
</style>
<h1>Hallo, Welt!</h1>

📚 Weitere Informationen zur Anwendung von Stilen findest du unter Stile & CSS.

Um JavaScript an den Browser zu senden, ohne eine Framework-Komponente (React, Svelte, Vue, Preact, SolidJS, AlpineJS, Lit) oder eine Astro-Integration (z.B. astro-XElement) zu verwenden, kannst du ein <script>-Tag in deiner Astro-Komponentenvorlage verwenden und JavaScript an den Browser senden, das auf globaler Ebene ausgeführt wird.

Standardmäßig werden <script>-Tags von Astro verarbeitet:

  • Alle Importe werden gebündelt, sodass sie lokale Dateien oder Node-Module importieren können.
  • Das verarbeitete Skript wird in den <head> deiner Seite mit type="module" eingefügt.
  • Wenn deine Komponente mehrmals auf einer Seite verwendet wird, wird das Skript-Tag nur einmal eingefügt.
<script>
// Verarbeitet! Gebündelt! ESM-Importe funktionieren,
// auch für npm-Pakete.
</script>

Um die Bündelung des Skripts zu vermeiden, kannst du das Attribut is:inline verwenden.

<script is:inline>
// Wird unverändert in den HTML-Code übernommen!
// ESM-Importe werden nicht relativ zur Datei aufgelöst.
</script>

Mehrere <script>-Tags können in derselben astro-Datei mit einer beliebigen Kombination der oben genannten Methoden verwendet werden.

📚 Siehe unsere Direktiven-Referenz für weitere Informationen über die Direktiven, die für <script>-Tags verfügbar sind.

Wann dies genutzt werden sollte: Wenn deine JavaScript-Datei innerhalb von public/ liegt.

Beachte, dass dieser Ansatz die JavaScript-Verarbeitung, die Bündelung und die Optimierungen überspringt, die von Astro bereitgestellt werden, wenn du die unten beschriebene import-Methode verwendest.

// Absoluter URL-Pfad
<script is:inline src="/irgendein-externes-skript.js"></script>

Wann dies genutzt werden sollte: Wenn dein externes Skript innerhalb von src/ liegt und es den ESM-Modultyp unterstützt.

Astro erkennt diese clientseitigen JavaScript-Importe und erstellt, optimiert und fügt das JS automatisch in die Seite ein.

// ESM-Import
<script>
import './irgendein-externes-skript.js';
</script>

📚 Lies über Astros eingebaute Komponenten.

📚 Erfahre mehr über die Verwendung von JavaScript-Framework-Komponenten in deinem Astro-Projekt.