System komponentów Astro
Komponenty .astro to podstawowy budulec aplikacji. Łączą znajomą składnię HTML z możliwościami JavaScript wykonywanego na serwerze.
Anatomia komponentu
---
// 1. FRONTMATTER — TypeScript/JavaScript, wykonywany na serwerze
interface Props {
title: string;
count?: number;
}
const { title, count = 0 } = Astro.props;
const doubled = count * 2;
---
<!-- 2. SZABLON — HTML z wyrażeniami -->
<div class="card">
<h2>{title}</h2>
<p>Podwojona wartość: {doubled}</p>
</div>
<!-- 3. STYLE — automatycznie scopowane -->
<style>
.card { border-radius: 8px; } /* nie wpłynie na inne .card w projekcie */
</style>
Props z TypeScript
Deklaracja interface Props pozwala na pełne typowanie:
---
interface Props {
variant: 'primary' | 'secondary';
disabled?: boolean;
onClick?: () => void;
}
const { variant, disabled = false } = Astro.props;
---
<button class={`btn btn-${variant}`} disabled={disabled}>
<slot />
</button>
Sloty — przekazywanie treści
<slot /> to miejsce, gdzie zostanie wstawiona zawartość przekazana do komponentu:
<!-- Definicja w Card.astro -->
<div class="card">
<slot name="header" /> <!-- named slot -->
<div class="body">
<slot /> <!-- domyślny slot -->
</div>
<slot name="footer" /> <!-- named slot -->
</div>
<!-- Użycie w innej stronie -->
<Card>
<h2 slot="header">Tytuł karty</h2>
<p>Treść trafia do domyślnego slotu.</p>
<a slot="footer" href="/more">Więcej →</a>
</Card>
Integracje z innymi frameworkami
Astro obsługuje komponenty React, Vue, Svelte i inne przez integracje:
npx astro add react
npx astro add vue
npx astro add svelte
Bez dyrektywy client:* komponenty są renderowane tylko na serwerze (zero JS):
---
import ReactCounter from './ReactCounter.tsx';
import VueWidget from './Widget.vue';
---
<!-- Statyczny HTML, zero hydratacji -->
<ReactCounter />
<!-- Hydratacja po załadowaniu, tylko gdy potrzebna -->
<VueWidget client:visible />
To jest serce Islands Architecture — interaktywność tylko tam, gdzie naprawdę potrzeba.