Scripts et gestion d'évènements.

Vous pouvez ajouter de l’interactivité à vos composants Astro sans utiliser un framework UI comme React, Svelte, Vue, etc. en utilisant la balise HTML <script>. Cela vous permet d’exécuter votre JavaScript dans le navigateur et ajouter des fonctionnalités à vos composants Astro.

Dans les fichiers .astro, vous pouvez ajouter du JavaScript côté client en ajoutant une (ou plusieurs) balises <script>.

Dans cet example, l’ajout du composant <Hello /> à un page enregistrera un message dans la console du navigateur.

src/compnonents/Hello.astro
<h1>Bienvenue, monde !</h1>
<script>
console.log('Bienvenue, console du navigateur !');
</script>

Par défaut, les balises <script> sont optimisées par Astro.

  • Toutes les importations seront regroupées, ce qui vous permettra d’importer des fichiers locaux ou des modules Node.
  • Le script optimisé sera injecté dans le <head> de votre page HTML avec type="module".
  • TypeScript est entièrement supporté, y compris l’importation de fichiers TypeScript.
  • Si votre composant est utilisé plusieurs fois sur un page, le script ne sera inclus qu’une seule fois.
src/components/Example.astro
<script>
// Optimisé ! Regroupé ! TypeScript supporté !
// L'importation de fichiers locaux et de modules Node est supportée.
<script>

Pour éviter le regroupement de script, vous pouvez utiliser la directive is:inline.

<script is:inline>
// Sera rendu dans le HTML exactement comme écrit.
// Les importations locales ne sont pas résolues et ne fonctionneront pas.
// S'il se trouve dans un composant, il se répète chaque fois que le composant est utilisé.
</script>

📚 Consultez notre page référence des directives pour plus d’informations sur les directives disponibles des balises <script>.

Vous voudriez écrire vos scripts dans un fichier séparé .js/.ts ou avoir besoin de référencer un script externe sur un autre serveur. Vous pouvez le faire en les référençant dans l’attribut src d’une balise <script>.

Quand l’utiliser : Si vos script est dedans src/

Astro va compiler, optimiser et ajouter ces scripts à la page pour vous, en suivant ses règles de regroupement de script

src/components/LocalScripts.astro
<!-- chemin relatif du script dans `src/scripts/local.js` -->
<script src="../scripts/local.js"></script>
<!-- fonctionne également pour les fichiers TypeScript locaux -->
<script src="./script-with-types.ts"></script>

Quand l’utiliser : Si votre fichier JavaScript se trouve à l’intérieur du dossier public/ ou sur un CDN.

Pour charger des scripts en dehors du dossier src/ de votre projet, incluez la directive is:inline. Cette approche permet d’éviter le traitement JavaScript, le regroupement et l’optimisation du JavaScript qui sont fournis par Astro lorsque vous importez des scripts comme décrit ci-dessus.

src/components/ExternalScripts.astro
<!-- chemin absolu du script à `public/my-script.js` -->
<script is:inline src="/my-script.js"></script>
<!-- URL complète vers un script sur un serveur distant -->
<script is:inline src="https://my-analytics.com/script.js"></script>

Gérer le onclick et d’autres évènements

Section titled Gérer le onclick et d’autres évènements

Certains frameworks d’interface utilisent une syntaxe personnalisée pour la gestion d’événements comme onClick={...} (React/Preact) ou @click="..." (Vue). Astro suit le HTML standard de plus près et n’utilise pas de syntaxe personnalisée pour les évènements.

Au lieu de cela, vous pouvez utiliser addEventListener dans une balise <script> pour gérer les interactions utilisateur.

src/components/AlertButton.astro
<button class="alert">Cliquez-moi !</button>
<script>
// Trouver tous les boutons avec la classe `alert` sur la page.
const buttons = document.querySelectorAll('button.alert');
// Gérer les clics sur chaque bouton.
buttons.forEach((button) => {
button.addEventListener('click', () => {
alert('Button was clicked !');
});
});
</script>

Composants Web avec des éléments personnalisés

Section titled Composants Web avec des éléments personnalisés

Vous pouvez créer vos propres éléments HTML ayant un comportement personnalisé en utilisant les composants web standards. Définir un élément personnalisé dans un composant .astro vous permet de créer des composants interactifs sans avoir besoin d’une bibliothèque de cadres d’interface utilisateur.

Dans cet exemple, nous définissons un nouvel élément HTML <astro-heart> qui suit le nombre de fois que vous cliquez sur le bouton cœur et met à jour le <span> avec le dernier compte.

src/components/AstroHeart.astro
<!-- Enveloppez les éléments du composant dans notre élément personnalisé "astro-heart" -->
<astro-heart>
<button aria-label="Heart">💜</button> × <span>0</span>
</astro-heart>
<script>
// Définir le comportement de notre nouveau type d'élément HTML.
class AstroHeart extends HTMLElement {
constructor() {
super();
let count = 0;
const heartButton = this.querySelector('button');
const countSpan = this.querySelector('span');
// À chaque fois que le bouton est cliqué, on met à jour le compte.
heartButton.addEventListener('click', () => {
count++;
countSpan.textContent = count;
});
}
}
// Dites au navigateur d'utiliser notre classe AstroHeart pour les éléments <astro-heart>.
customElements.define('astro-heart', AstroHeart);
</script>

Il y a deux avantages à utiliser un élément personnalisé ici:

  1. Au lieu de chercher dans toute la page en utilisant document.querySelector(), vous pouvez utiliser this.querySelector(), qui ne recherche que dans l’instance courante de l’élément personnalisé. Cela permet de travailler plus facilement avec les enfants d’une seule instance de composant à la fois.

  2. Bien qu’un <script> ne s’exécute qu’une seule fois, le navigateur exécutera la méthode constructor() de notre élément personnalisé chaque fois qu’il trouvera <astro-heart> sur la page. Cela signifie que vous pouvez écrire du code en toute sécurité pour un composant à la fois, même si vous avez l’intention d’utiliser ce composant plusieurs fois sur une page.

Vous pouvez en savoir plus sur les éléments personnalisés dans le guide des composants Web réutilisables de web.dev et dans l’introduction aux composants personnalisés de MDN.

Passer les variables frontmatter aux scripts

Section titled Passer les variables frontmatter aux scripts

Dans les composants Astro, le code dans le frontmatter entre les clôtures “---” s’exécute sur le serveur et n’est pas disponible dans le navigateur. Pour envoyer des variables du serveur au client, nous avons besoin d’un moyen de stocker nos variables et de les lire lorsque le JavaScript s’exécute dans le navigateur.

Une façon de le faire est d’utiliser les attributs data-* pour stocker la valeur des variables dans votre sortie HTML. Les scripts, y compris les éléments personnalisés, peuvent alors lire ces attributs en utilisant la propriété dataset d’un élément une fois que votre HTML se charge dans le navigateur.

Dans cet exemple de composant, une propriété message est stockée dans un attribut data-message, de sorte que l’élément personnalisé puisse lire this.dataset.message et obtenir la valeur de la propriété dans le navigateur.

src/components/AstroGreet.astro
---
const { message = 'Welcome, world!' } = Astro.props;
---
<!-- Stocker la propriété de message comme attribut de données. -->
<astro-greet data-message={message}>
<button>Saluer!</button>
</astro-greet>
<script>
class AstroGreet extends HTMLElement {
constructor() {
super();
// Lisez le message de l’attribut data.
const message = this.dataset.message;
const button = this.querySelector('button');
button.addEventListener('click', () => {
alert(message);
});
}
}
customElements.define('astro-greet', AstroGreet);
</script>

Maintenant, nous pouvons utiliser notre composant plusieurs fois et être accueillis par un message différent pour chacun.

src/pages/example.astro
---
import AstroGreet from '../components/AstroGreet.astro';
---
<!-- Utilisez le message par défaut: "Bienvenue, monde!" -->
<AstroGreet />
<!-- Utiliser des messages personnalisés passés comme prop. -->
<AstroGreet message="Belle journée pour construire des composants !" />
<AstroGreet message="Content que tu sois là ! 👋" />