Aller au contenu

Composants

Les composants Astro sont les éléments de base de tout projet Astro. Il s’agit de composants de template HTML uniquement, sans exécution côté client, qui utilisent l’extension de fichier .astro.

Les composants Astro sont extrêmement flexibles. Un composant Astro peut être aussi petit qu’un extrait de HTML, comme une collection de balises <meta> communes qui facilitent le travail de référencement. Les composants peuvent être des éléments réutilisables de l’interface utilisateur, comme un en-tête ou une fiche de profil. Les composants Astro peuvent même contenir une mise en page entière ou, lorsqu’ils sont situés dans le dossier spécial src/pages/, être une page entière.

La chose la plus importante à savoir à propos des composants Astro est qu’ils ne sont pas rendus sur le client. Ils sont rendus en HTML soit au moment de la construction, soit à la demande. Vous pouvez inclure du code JavaScript à l’intérieur du frontmatter de votre composant, et tout ce code sera retiré de la page finale envoyée aux navigateurs de vos utilisateurs. Le résultat est un site plus rapide, sans aucune empreinte JavaScript ajoutée par défaut.

Lorsque votre composant Astro nécessite une interactivité côté client, vous pouvez ajouter des balises HTML standard <script> ou des composants UI Framework en tant qu’« îlots client ».

Pour les composants qui doivent rendre un contenu personnalisé ou dynamique, vous pouvez différer leur rendu sur le serveur en ajoutant une directive serveur. Ces « îlots de serveur » rendront leur contenu lorsqu’il sera disponible, sans retarder le chargement complet de la page.

Un composant Astro est composé de deux parties principales : le Script du composant et le Template du composant. Chacune de ces parties s’occupe de faire une tâche différente, mais ensemble, constituent un cadre facile d’utilisation et assez expressif pour gérer tout ce que vous voulez construire.

src/components/EmptyComponent.astro
---
// Script du composant (JavaScript)
---
<!-- Template du composant (HTML + Expressions JS) -->

Astro utilise des barres de code (---) pour identifier le script du composant dans votre composant Astro. Si vous avez déjà écrit du Markdown avant, vous pourriez être déjà familier avec un concept similaire appelé frontmatter. Astro est directement inspiré de cela.

Vous pouvez utiliser le script du composant pour écrire du code JavaScript qui vous aidera à construire votre template. Cela peut inclure :

  • Importer d’autres composants Astro
  • Importer des composants de Framework, comme React
  • Importer des données, comme un fichier JSON
  • Récupérer le contenu d’une API ou d’une base de données
  • Créer des variables que vous voulez référencer dans votre template
src/components/MyComponent.astro
---
import SomeAstroComponent from '../components/SomeAstroComponent.astro';
import SomeReactComponent from '../components/SomeReactComponent.jsx';
import someData from '../data/pokemon.json';
// Accéder aux props de composants transmis, comme `<X title="Hello, World" />`
const { title } = Astro.props;
// Récupérer des données externes, même à partir d'une API ou d'une base de données privée
const data = await fetch('SOME_SECRET_API_URL/users').then(r => r.json());
---
<!-- Votre template ici ! -->

Les barres de code sont conçues pour garantir que le code JavaScript que vous écrivez à l’intérieur « ne puisse pas s’échapper ». Il ne sera pas visible dans le frontend de votre application et ne tombera pas entre les mains de votre utilisateur. Vous pouvez écrire du code JavaScript coûteux (en terme de performance) ou sensible (comme un appel à votre base de données privée) sans vous soucier qu’il se retrouve dans le navigateur l’utilisateur.

En dessous du script du composant se trouve le template du composant. Ce dernier détermine le HTML résultant de votre composant.

Si vous écrivez du HTML simple ici, votre composant affichera cet HTML dans toutes les pages où il est importé et utilisé.

De plus, la syntaxe du template du composant Astro prend également en charge les expressions JavaScript, les balises <style> et <script> Astro, les composants importés et les directives spéciales Astro. Les données et les valeurs définies (à la compilation) dans le script du composant peuvent être utilisées dans le template du composant pour produire du HTML dynamiquement créé.

src/components/MyFavoritePokemon.astro
---
// Votre script du composant ici !
import Banner from '../components/Banner.astro';
import Avatar from '../components/Avatar.astro';
import ReactPokemonComponent from '../components/ReactPokemonComponent.jsx';
const myFavoritePokemon = [/* ... */];
const { title } = Astro.props;
---
<!-- Les commentaires HTML sont supportés ! -->
{/* La syntaxe des commentaires JavaScript est aussi valide ! */}
<Banner />
<h1>Hello, world!</h1>
<!-- Utilisez les props et autres variables du script du composant : -->
<p>{title}</p>
<!-- Retarder le rendu des composants et fournir un contenu de chargement de secours : -->
<Avatar server:defer>
<svg slot="fallback" class="generic-avatar" transition:name="avatar">...</svg>
</Avatar>
<!-- Incluez d'autres composants avec une directive `client:` pour l'hydrater : -->
<ReactPokemonComponent client:visible />
<!-- Mixez du HTML avec des expressions JavaScript, similaire au JSX : -->
<ul>
{myFavoritePokemon.map((data) => <li>{data.name}</li>)}
<ul>
<!-- Utilisez une directive de template pour créer des classes à partir de plusieurs chaînes ou même d'objets ! -->
<p class:list={["add", "dynamic", {classNames : true}]} />

Les composants sont conçus pour être réutilisables et composables. Vous pouvez utiliser des composants à l’intérieur d’autres composants pour créer une interface utilisateur de plus en plus complexe. Par exemple, un composant Button pourrait être utilisé pour créer un composant ButtonGroup comme ceci :

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

Un composant Astro peut définir et accepter des props (diminutif pour « propriétés »). Ces dernières deviennent alors disponibles dans le template du composant pour le rendu du HTML. Les props sont accessibles à l’aide de la variable globale Astro.props dans le frontmatter, ou script du composant.

Voici un exemple de composant qui reçoit une propriété nommée greeting et une autre nommée name. Notez que les props à recevoir sont déstructurées de l’objet global Astro.props.

src/components/GreetingHeadline.astro
---
// Utilisation : <GreetingHeadline greeting="Comment ça va" name="Partenaire" />
const { greeting, name } = Astro.props;
---
<h2>{greeting}, {name} !</h2>

Ce composant, lorsqu’il est importé et rendu dans d’autres composants, mises en page ou pages Astro, peut transmettre ces props sous forme d’attributs :

src/components/GreetingCard.astro
---
import GreetingHeadline from './GreetingHeadline.astro';
const name = 'Astro';
---
<h1>Carte de bienvenue</h1>
<GreetingHeadline greeting="Salut" name={name} />
<p>J'espère que vous passez une merveilleuse journée !</p>

Vous pouvez également définir le type de vos props avec TypeScript en créant une interface nommée Props. Astro sélectionnera automatiquement l’interface Props dans le frontmatter et donnera des avertissements/erreurs de type. Ces props peuvent également recevoir des valeurs par défaut lorsqu’elles sont déstructurées à partir d’Astro.props.

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

Les props de composant peuvent recevoir des valeurs par défaut à utiliser lorsqu’aucune n’est fournie.

src/components/GreetingHeadline.astro
---
const { greeting = "Salut", name = "Astronaute" } = Astro.props;
---
<h2>{greeting}, {name}!</h2>

L’élément <slot /> est un emplacement réservé pour du contenu HTML externe, vous permettant d’injecter des éléments enfants depuis d’autres fichiers, dans le template de votre composant.

Par défaut, tous les éléments enfants passés à un composant seront rendus dans son <slot />.

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 /> <!-- les élement enfants seront insérés ici -->
<Footer />
</div>
src/pages/fred.astro
---
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="Page de Fred">
<h2>Tout ce qui est a savoir sur Fred</h2>
<p>Voici quelques trucs à propos de Fred.</p>
</Wrapper>

Ce modèle est la base d’un Composant Layout dans Astro : une page entière de contenu HTML peut être « enveloppée » avec des balises <Layout></Layout> et envoyée au composant pour être rendue à l’intérieur des éléments de page communs qui y sont définis.

Un composant Astro peut aussi avoir des emplacements nommés. Cela vous permet de ne faire passer que des éléments HTML avec le nom d’emplacement (slot) correspondant, au niveau de l’emplacement.

Les emplacements (slots) sont nommés à l’aide de l’attribut name :

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" /> <!-- les enfants avec l'attribut `slot="after-header" iront ici -->
<Logo />
<h1>{title}</h1>
<slot /> <!-- les enfants sans `slot` ou avec l'attribut `slot="default"`iront ici -->
<Footer />
<slot name="after-footer" /> <!-- les enfants avec l'attribut `slot="after-footer"` iront ici -->
</div>

Pour injecter du contenu HTML dans un emplacement (slot) particulier, utilisez l’attribut slot sur n’importe quel élément enfant pour spécifier le nom de l’emplacement (slot). Tous les autres éléments enfants du composant seront injectés dans le <slot /> par défaut (sans nom).

src/pages/fred.astro
---
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="Page de Fred">
<img src="https://my.photo/fred.jpg" slot="after-header" />
<h2>Tout ce qui est a savoir sur Fred</h2>
<p>Voici quelques trucs à propos de Fred.</p>
<p slot="after-footer">Copyright 2022</p>
</Wrapper>

Pour faire passer plusieurs éléments HTML dans l’espace réservé <slot/> d’un composant sans qu’ils soient enveloppés par une balise <div>, utilisez l’attribut slot="" sur le composant <Fragment/> d’Astro:

src/components/CustomTable.astro
---
// Créer un tableau personnalisé avec des emplacements (slot) nommés pour le contenu HEAD et BODY du contenu.
---
<table class="bg-white">
<thead class="sticky top-0 bg-white"><slot name="header" /></thead>
<tbody class="[&_tr:nth-child(odd)]:bg-gray-100"><slot name="body" /></tbody>
</table>

Injecter plusieurs lignes et colonnes de contenu HTML en utilisant un attribut slot="" pour spécifier le contenu "header" et "body". Les éléments HTML individuels peuvent également être stylisés :

src/components/StockTable.astro
---
import CustomTable from './CustomTable.astro';
---
<CustomTable>
<Fragment slot="header"> <!-- passer l'en-tête du tableau -->
<tr><th>Nom du produit</th><th>Unités en stock</th></tr>
</Fragment>
<Fragment slot="body"> <!-- passer le corps du tableau -->
<tr><td>Tongs</td><td>64</td></tr>
<tr><td>Bottes</td><td>32</td></tr>
<tr><td>Baskets</td><td class="text-red-500">0</td></tr>
</Fragment>
</CustomTable>

Notez que les emplacements nommés doivent être des enfants immédiats du composant. Il n’est pas possible de transmettre des emplacements nommés à travers des éléments imbriqués.

Contenu par défaut pour les emplacements

Titre de la section Contenu par défaut pour les emplacements

Les slots peuvent également restituer du contenu de secours (ou « fallback »). Lorsqu’aucun enfant correspondant n’est transmis à un slot, un élément <slot /> restituera ses propres enfants fictifs.

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>Ceci est mon contenu par defaut, s'il n'y a pas d'enfants passés à l'emplacement</p>
</slot>
<Footer />
</div>

Le contenu de repli ne sera affiché que si aucun élément correspondant avec l’attribut slot=“name” n’est transmis à un slot nommé.

Astro transmet un slot vide lorsqu’un élément slot existe, mais qu’il n’y a pas de contenu à transmettre. Le contenu de repli ne peut pas être utilisé par défaut lorsqu’un slot vide est transmis. Le contenu de repli n’est affiché que quand aucun élément slot ne peut être trouvé.

Les emplacements peuvent être transférés à d’autres composants. Par exemple, lorsque l’on crée des mises en page imbriquées :

src/layouts/BaseLayout.astro
---
---
<html lang="fr">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<slot name="head" />
</head>
<body>
<slot />
</body>
</html>
src/layouts/HomeLayout.astro
---
import BaseLayout from './BaseLayout.astro';
---
<BaseLayout>
<slot name="head" slot="head" />
<slot />
</BaseLayout>

Maintenant, les emplacements par défaut et head passés à HomeLayout seront transférés au parent BaseLayout.

src/pages/index.astro
---
import HomeLayout from '../layouts/HomeLayout.astro';
---
<HomeLayout>
<title slot="head">Astro</title>
<h1>Astro</h1>
</HomeLayout>

Astro prend en charge l’importation et l’utilisation de fichiers .html en tant que composants ou le placement de ces fichiers dans le sous-répertoire src/pages en tant que pages. Vous souhaiterez peut-être utiliser des composants HTML si vous réutilisez le code d’un site existant construit sans framework, ou si vous voulez vous assurer que votre composant n’ai pas de fonctionnalités dynamiques.

Les composants HTML ne doivent contenir que du code HTML valide et ne disposent donc pas des fonctionnalités clés des composants Astro :

Apprendre comment utiliser les composants de framework JavaScript dans votre projet Astro.
Contribuer

Comment pouvons-nous vous aider ?

Créer une issue GitHub

Le moyen le plus rapide d'alerter notre équipe d'un problème.

Communauté