Composants

Les composants Astro sont les blocs de base de tout projet Astro. Ce sont des composants avec seulement du HTML, sans exécution côté client.

Si vous connaissez le HTML, vous en savez déjà assez pour écrire votre premier composant Astro.

La syntaxe du composant Astro est un sur-ensemble de HTML. La syntaxe a été conçue pour être familière à toute personne ayant de l’expérience dans l’écriture de HTML ou JSX, et ajoute la prise en charge de l’inclusion de composants et d’expressions JavaScript. Vous pouvez repérer un composant Astro par son extension de fichier : .astro.

Les composants Astro sont extrêmement flexibles. Souvent, un composant Astro contiendra une interface utilisateur réutilisable sur la page, comme un en-tête ou une carte de profil. À d’autres moments, un composant Astro peut contenir un petit extrait de code HTML, comme une collection de balises <meta> courantes qui facilitent le travail avec le référencement. Les composants Astro peuvent même contenir la mise en page entière d’une page.

La chose la plus importante à savoir sur les composants Astro est qu’ils produisent du HTML lors de la compilation. Même si vous exécutez du code JavaScript à l’intérieur de vos composants, tout s’exécutera à l’avance, supprimé de la page finale que vous envoyez à vos utilisateurs. Le résultat est un site plus rapide, avec une empreinte JavaScript nulle ajoutée par défaut.

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) -->

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>

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 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 propriétés passées dans le composant, comme `<X title="Hello, World" />`
const {title} = Astro.props;
// Récupérer des données externes, même depuis une API privée ou une base de données
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”. Ce code n’apparaîtra pas dans le code final de votre page et ne sera pas visible à vos 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. Le template du composant 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 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 ReactPokemonComponent from '../components/ReactPokemonComponent.jsx';
const myFavoritePokemon = [/*... */];
---
<!-- les commentaires HTML sont supportés ! -->
<h1>Hello, world!</h1>
<!-- Utilisez les propriétés et autres variables du script du composant : -->
<p>Mon pokemon favori est : {Astro.props.title}</p>
<!-- 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}]} />

Vous pouvez définir des variables JavaScript locales dans le script du composant Astro. Vous pouvez ensuite injecter ces variables dans le template HTML du composant à en utilisant des expressions de type JSX !

Des variables locales peuvent être ajoutées dans le HTML en utilisant la syntaxe des accolades :

src/components/Variables.astro
---
const name = "Astro";
---
<div>
<h1>Hello {name}!</h1> <!-- Affichera <h1>Hello Astro!</h1> -->
</div>

Les variables locales peuvent être utilisées entre accolades pour transmettre des valeurs d’attribut aux éléments HTML et aux composants :

src/components/DynamicAttributes.astro
---
const name = "Astro";
---
<h1 class={name}>Les expressions d'attributs sont prises en charge</h1>
<MyComponent templateLiteralNameAttribute={`MonNomEst${name}`} />

Les variables locales peuvent être utilisées dans des fonctions de type JSX pour produire des éléments HTML générés dynamiquement :

src/components/DynamicHtml.astro
---
const items = ["Chien", "Chat", "Ornithorynque"];
---
<ul>
{items.map((item) => (
<li>{item}</li>
))}
</ul>

Astro peut afficher conditionnellement du HTML à l’aide d’opérateurs logiques JSX et d’expressions ternaires.

src/components/ConditionalHtml.astro
---
const visible = true;
---
{visible && <p>Montre moi!</p>}
{visible ? <p>Montre moi!</p> : <p>Sinon montre moi!</p>}

Vous pouvez également utiliser des balises dynamiques en définissant une variable affectée d’un nom de balise HTML ou d’un composant importé :

src/components/DynamicTags.astro
---
import MyComponent from "./MyComponent.astro";
const Element = 'div'
const Component = MyComponent;
---
<Element>Salut!</Element> <!-- s'affiche comme <div>Salut!</div> -->
<Component /> <!-- s'affiche comme <MyComponent /> -->

Lors de l’utilisation de balises dynamiques :

  • Les noms de variables doivent commencer par une lettre majuscules. Par exemple, utilisez Element, et non element. Sinon, Astro essaiera de restituer le nom de votre variable sous la forme d’une balise HTML littéralement.

  • Les directives d’hydratation ne sont pas prises en charge. Lorsque vous utilisez les directives d’hydratation client:*, Astro doit savoir quels composants regrouper pour la production, et le modèle de balise dynamique empêche cela de fonctionner.

Fragments et éléments multiples

Section titled Fragments et éléments multiples

Un template de composant Astro peut restituer plusieurs éléments sans avoir besoin de tout envelopper dans un seul <div> ou <>, contrairement à JavaScript ou JSX.

src/components/RootElements.astro
---
// Template with multiple elements
---
<p>Pas besoin d'envelopper les éléments dans un seul élément conteneur.</p>
<p>Astro prend en charge plusieurs éléments à la racine du template</p>

Cependant, lorsque vous utilisez une expression pour créer dynamiquement plusieurs éléments, vous devez entourer ces éléments dans un fragment comme vous le feriez dans du JavaScript ou du JSX. Astro prend en charge l’utilisation de <Fragment> </Fragment> ou de la syntaxe abrégée <> </>.

src/components/FragmentWrapper.astro
---
const items = ["Chien", "Chat", "Ornithorynque"];
---
<ul>
{items.map((item) => (
<>
<li>Rouge {item}</li>
<li>Bleu {item}</li>
<li>Vert {item}</li>
</>
))}
</ul>

Les Fragments peuvent aussi être utiles pour éviter d’utiliser des éléments conteneurs lors de l’ajout de directives set:*, comme dans l’exemple suivant :

src/components/SetHtml.astro
---
const htmlString = '<p>Contenu HTML brut</p>';
---
<Fragment set:html={htmlString} />

Différences entre Astro et JSX

Section titled Différences entre Astro et JSX

La syntaxe du composant Astro est un sur-ensemble de HTML. Il a été conçu pour être familier à toute personne ayant une expérience HTML ou JSX, mais il existe quelques différences clés entre les fichiers .astro et JSX.

Dans Astro, vous utilisez le format standard kebab-case pour tous les attributs HTML au lieu du camelCase utilisé dans JSX. Cela fonctionne même pour class, qui n’est pas pris en charge par React.

<div className="box" dataValue="3" />
<div class="box" data-value="3" />

Dans Astro, vous pouvez utiliser des commentaires HTML standard ou des commentaires de style JavaScript.

example.astro
---
---
<!-- La syntaxe de commentaire HTML est valide dans les fichiers.astro -->
{/* La syntaxe des commentaires JS est également valide */}

Un composant Astro peut définir et accepter des “props”. Ces props deviennent alors accessible dans le template du composant pour le rendu du HTML. Les props sont disponibles sur la variable globale Astro.props entre les barres de codes.

Voici un exemple de composant qui reçoit un prop nommé greeting et un prop nommé name. Notez que les props à recevoir sont déstructurés 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 utilisé dans d’autres composants standards, Composants Layout ou pages Astro, peut recevoir 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 Script du Composant et donnera des avertissements/erreurs de type. Ces props peuvent également recevoir des valeurs par défaut lorsqu’ils sont déstructurés à partir d’ Astro.props.

---
// Votre script du composant ici !
---
<style>
/* restreint au composant, les autres balises H1 sur la page restent les mêmes */
h1 { color: red };
</style>
<h1>Hello, world!</h1>

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">
<img src="https://my.photo/fred.jpg" slot="after-header">
<h2>Tout ce qui est a savoir sur Fred</h2>
<p>Voici quelques truc à 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 Layout pour être rendu à l’intérieur des éléments de page communs.

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.

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>
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 truc à propos de Fred.</p>
<p slot="after-footer">Copyright 2022</p>
</Wrapper>

Utilisez un attribut slot="my-slot" sur l’élément enfant que vous voulez passer à un emplacement correspondant <slot name="my-slot" /> dans votre composant.

Contenu par defaut pour les emplacement

Section titled Contenu par defaut pour les emplacement

Les emplacements peuvent également restituer du contenu par defaut. Lorsqu’il n’y a pas d’enfants correspondants passés à un emplacement, un élément <slot /> affichera ses propres enfants.

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>

Les balises CSS <style> sont également permises dans le template du composant.

Elles peuvent être utilisées pour donner du style à vos composants, et toutes les règles de style sont automatiquement limitées à la portée du composant lui-même pour éviter les conflits CSS dans les applications volumineuses.

src/components/StyledHeading.astro
---
// Le script du composant ici !
---
<style>
/* restreint au composant, les autres balises H1 de la page resteront inchangés */
h1 { color: red }
</style>
<h1>Hello, world!</h1>

📚 Allez voir notre Guide des styles pour plus d’informations sur l’application de styles.

Les composants Astro prennent en charge l’ajout d’interactivité côté client à l’aide de balises HTML <script> standard.

Les scripts peuvent être utilisés pour ajouter des écouteurs d’événements, envoyer des données d’analyse, jouer des animations et tout ce que JavaScript peut faire sur le Web.

src/components/ConfettiButton.astro
<button data-confetti-button>Célébrez !</button>
<script>
// Importe des modules npm.
import confetti from 'canvas-confetti';
// Trouve des éléments du DOM sur la page.
const buttons = document.querySelectorAll('[data-confetti-button]');
// Ajoute des écouteurs d'événements pour déclencher des confettis lorsqu'un bouton est cliqué
buttons.forEach((button) => {
button.addEventListener('click', () => confetti());
});
</script>

Par défaut, les balises <script> sont optimisées par Astro, ajoutant la prise en charge de l’importation de modules npm, de l’écriture de TypeScript, etc.

📚 Consultez notre guide sur les scripts pour plus de détails.

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 :

📚 En savoir plus sur les composants intégrés d’Astro (EN).

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