Astro stellt die Seiten, Layouts, Komponenten und das Server-Rendering für eine EmDash-Site bereit. Dieser Leitfaden behandelt die Astro-Konzepte, die von den aktuellen EmDash-Templates verwendet werden. Er setzt voraus, dass Sie WordPress-Themes und PHP-Templates bereits verstehen.
Für Framework-Funktionen, die nicht EmDash-spezifisch sind, nutzen Sie die Astro-Dokumentation.
Projektstruktur
Eine Astro-Site weist jeder Dateiart ein eigenes Verzeichnis zu. Die aktuellen EmDash-Templates verwenden diese Struktur:
| WordPress | Astro | Zweck |
|---|---|---|
index.php, single.php, page.php | src/pages/ | URL-Routen |
template-parts/ | src/components/ | Wiederverwendbares Markup |
header.php und footer.php | src/layouts/ | Gemeinsame Seitenhüllen |
style.css | src/styles/ | Site-Stile |
| Plugin- und Datenbank-Setup | astro.config.mjs | Integrationen und Server-Adapter |
| Theme-Setup-Daten | seed/seed.json | Sammlungen, Menüs und Beispielinhalte |
Das Blog-Template verwendet Routenverzeichnisse, die zu seinen öffentlichen URLs passen:
src/
├── components/
│ └── PostCard.astro
├── layouts/
│ └── Base.astro
├── pages/
│ ├── index.astro
│ ├── pages/
│ │ └── [slug].astro
│ └── posts/
│ ├── index.astro
│ └── [slug].astro
└── live.config.ts
Astro-Komponenten
Eine .astro-Komponente kombiniert serverseitiges TypeScript und ein HTML-Template. Code zwischen den ----Fences läuft auf dem Server. Das Markup unter dem zweiten Fence wird zum HTML der Antwort.
Die folgende Komponente deklariert Props in ihrem Frontmatter und rendert sie in ihrem Template:
---
interface Props {
title: string;
excerpt?: string;
href: string;
}
const { title, excerpt, href } = Astro.props;
---
<article>
<h2><a href={href}>{title}</a></h2>
{excerpt && <p>{excerpt}</p>}
</article>
Astro maskiert Werte, die mit {value} gerendert werden. Imports, Datenbankabfragen und andere Serverarbeit gehören ins Frontmatter.
Template-Ausdrücke
Astro-Templates verwenden geschweifte Klammern an den Stellen, an denen ein PHP-Template in <?php ?> wechseln würde. Die häufigsten Muster in EmDash-Templates sind Werte, Bedingungen und das Mapping von Arrays:
| Ziel | Astro-Syntax |
|---|---|
| Einen Wert ausgeben | {post.data.title} |
| Rendern, wenn ein Wert existiert | {post.data.excerpt && <p>{post.data.excerpt}</p>} |
| Zwischen zwei Ergebnissen wählen | {posts.length === 0 ? <p>No posts yet.</p> : <PostList />} |
| Eine Liste rendern | {posts.map((post) => <PostCard title={post.data.title} excerpt={post.data.excerpt} href={"/posts/" + post.id} />)} |
Der Ausdruck kann im Frontmatter vorbereitete Variablen, Werte aus Astro.props oder von einer EmDash-Abfrage zurückgegebene Daten verwenden. Astro maskiert String-Werte standardmäßig; verwenden Sie für strukturierten Rich Text einen Renderer wie <PortableText />, anstatt HTML einzuschleusen.
Props und Slots
Props sind mit den $args vergleichbar, die an get_template_part() übergeben werden. Sie machen jede Eingabe explizit und können von TypeScript geprüft werden.
Slots lassen ein übergeordnetes Element Markup in eine Komponente übergeben. Ein Default-Slot eignet sich für Seiteninhalte, während benannte Slots zusätzliche Einfügepunkte bereitstellen:
---
interface Props {
title: string;
}
const { title } = Astro.props;
---
<article>
<h2>{title}</h2>
<slot />
<footer><slot name="footer" /></footer>
</article>
Die folgende Seite füllt beide Slots:
---
import Card from "../components/Card.astro";
---
<Card title="Latest post">
<p>The main card content.</p>
<a slot="footer" href="/posts/latest">Read the post</a>
</Card>
Slots sind lokal für den Komponentenaufruf. Sie verhalten sich nicht wie WordPress-Actions, die Callbacks empfangen können, die an anderer Stelle registriert wurden.
Layouts
Ein Layout besitzt die gemeinsame Dokumentstruktur, die ein WordPress-Theme oft auf header.php und footer.php aufteilt. Seiten importieren das Layout und übergeben ihren Inhalt über dessen Slot.
Das folgende Layout stellt eine Dokumenthülle bereit:
---
interface Props {
title: string;
}
const { title } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>{title}</title>
</head>
<body>
<header><a href="/">My site</a></header>
<main><slot /></main>
</body>
</html>
Die folgende Seite liefert den Titel und den Hauptinhalt des Layouts:
---
import Base from "../layouts/Base.astro";
---
<Base title="Home">
<h1>Latest posts</h1>
</Base>
Dateibasiertes Routing
Dateien in src/pages/ definieren Routen. Dateinamen in eckigen Klammern erzeugen dynamische Segmente.
| Datei | URL |
|---|---|
src/pages/index.astro | / |
src/pages/posts/index.astro | /posts |
src/pages/posts/[slug].astro | /posts/hello-world |
src/pages/pages/[slug].astro | /pages/about |
In src/pages/posts/[slug].astro enthält Astro.params.slug den Wert aus der URL. Lesen Sie Astro-Routing für Rest-Parameter, Weiterleitungen und andere Routing-Funktionen.
Server-Rendering
Aktuelle EmDash-Templates verwenden output: "server" in astro.config.mjs. Eine Seite kann daher bei jeder Anfrage die Datenbank abfragen, sodass veröffentlichte Inhalte nicht von einem neuen statischen Build abhängen.
Fügen Sie einer EmDash-Theme-Route kein getStaticPaths() hinzu, es sei denn, die Site behandelt EmDash bewusst als Datenquelle zur Build-Zeit. Die mitgelieferten Themes werden serverseitig gerendert.
Lesen Sie Astro On-Demand-Rendering für das Verhalten auf Framework-Ebene.
EmDash-Inhalte abfragen
EmDash umhüllt die Live-Content-Collections von Astro mit getEmDashCollection() und getEmDashEntry(). Sammlungsergebnisse enthalten ein entries-Array. Ergebnisse für einzelne Einträge enthalten entry, das null ist, wenn kein veröffentlichter Eintrag passt.
Das folgende Archiv verwendet dieselbe Sortierung und dieselben Bezeichner wie das aktuelle Blog-Template:
---
import { getEmDashCollection } from "emdash";
import Base from "../../layouts/Base.astro";
const { entries: posts, error } = await getEmDashCollection("posts", {
orderBy: { published_at: "desc" },
});
if (error) {
return new Response("Could not load posts", { status: 500 });
}
---
<Base title="Posts">
{posts.map((post) => (
<article>
<h2><a href={`/posts/${post.id}`}>{post.data.title}</a></h2>
{post.data.excerpt && <p>{post.data.excerpt}</p>}
</article>
))}
</Base>
post.id ist der von Astro bereitgestellte Routenbezeichner und normalerweise der Slug des Eintrags. post.data.id ist der Datenbankbezeichner. Verwenden Sie data.id, wenn eine API die gespeicherte Inhalts-ID erwartet, etwa bei Taxonomie- oder Kommentar-Hilfsfunktionen.
Die folgende dynamische Route sucht einen Beitrag anhand des Slugs in der URL und rendert sein Portable-Text-Feld:
---
import { decodeSlug, getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";
import Base from "../../layouts/Base.astro";
const slug = decodeSlug(Astro.params.slug);
if (!slug) return Astro.rewrite("/404");
const { entry: post, error } = await getEmDashEntry("posts", slug);
if (error) return new Response("Could not load the post", { status: 500 });
if (!post) return Astro.rewrite("/404");
---
<Base title={post.data.title}>
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article>
</Base>
Weiter mit Astro
EmDash-Templates verwenden außerdem Komponentenstile und kleine Browser-Skripte, aber das sind gewöhnliche Astro-Funktionen und keine EmDash-Konzepte. Lesen Sie Styles und CSS für Scoped- und globale Stile sowie Skripte und Event-Handling, wenn eine Komponente browserseitiges Verhalten benötigt.