Scripts y manejo de eventos
Puedes enviar JavaScript al navegador y añadir funcionalidad a tus componentes de Astro utilizando etiquetas <script> en la plantilla del componente.
Los scripts añaden interactividad a tu sitio, como el manejo de eventos o la actualización dinámica de contenido, sin la necesidad de un framework de UI como React, Svelte o Vue. Esto evita la sobrecarga de enviar el JavaScript del framework y no requiere que conozcas ningún framework adicional para crear un sitio web o aplicación completo.
Scripts en el lado del cliente
Sección titulada “Scripts en el lado del cliente”Los scripts se pueden utilizar para añadir detectores de eventos, enviar datos de analíticas, reproducir animaciones y todo lo demás que JavaScript puede hacer en la web.
Astro mejora automáticamente la etiqueta HTML estándar <script> con bundling, TypeScript y más. Consulta cómo procesa Astro los scripts para obtener más detalles.
<button data-confetti-button>Celebrate!</button>
<script> // Import from npm package. import confetti from 'canvas-confetti';
// Find our component DOM on the page. const buttons = document.querySelectorAll('[data-confetti-button]');
// Add event listeners to fire confetti when a button is clicked. buttons.forEach((button) => { button.addEventListener('click', () => confetti()); });</script>Procesamiento de scripts
Sección titulada “Procesamiento de scripts”Por defecto, Astro procesa las etiquetas <script> que no contienen atributos (aparte de src) de las siguientes maneras:
- Soporte de TypeScript: Todos los scripts son TypeScript por defecto.
- Bundling de importaciones: Importa archivos locales o módulos de npm, que se agruparán en un bundle.
- Type Module: Los scripts procesados se convierten en
type="module"automáticamente. - Deduplicación: Si un componente que contiene un
<script>se usa varias veces en una página, el script solo se incluirá una vez. - Inlining automático: Si el script es lo suficientemente pequeño, Astro lo insertará directamente en el HTML para reducir el número de solicitudes.
<script> // Processed! Bundled! TypeScript! // Importing local scripts and from npm packages works.</script>Scripts no procesados
Sección titulada “Scripts no procesados”Astro no procesará una etiqueta <script> si tiene algún atributo que no sea src.
Puedes añadir la directiva is:inline para optar por no procesar un script de manera intencionada.
<script is:inline> // Will be rendered into the HTML exactly as written! // Not transformed: no TypeScript and no import resolution by Astro. // If used inside a component, this code is duplicated for each instance.</script>Incluir archivos JavaScript en tu página
Sección titulada “Incluir archivos JavaScript en tu página”Es posible que desees escribir tus scripts como archivos .js/.ts separados o que necesites hacer referencia a un script externo en otro servidor. Puedes hacer esto haciendo referencia a ellos en el atributo src de una etiqueta <script>.
Importar scripts locales
Sección titulada “Importar scripts locales”Cuándo usar esto: cuando tu script se encuentra dentro de src/.
Astro procesará estos scripts de acuerdo con las reglas de procesamiento de scripts.
<!-- relative path to script at `src/scripts/local.js` --><script src="../scripts/local.js"></script>
<!-- also works for local TypeScript files --><script src="./script-with-types.ts"></script>Cargar scripts externos
Sección titulada “Cargar scripts externos”Cuándo usar esto: cuando tu archivo JavaScript se encuentra dentro de public/ o en una CDN.
Para cargar scripts fuera de la carpeta src/ de tu proyecto, incluye la directiva is:inline. Este enfoque omite el procesamiento, empaquetado (bundling) y las optimizaciones de JavaScript que proporciona Astro cuando importas scripts como se describió anteriormente.
<!-- absolute path to a script at `public/my-script.js` --><script is:inline src="/my-script.js"></script>
<!-- full URL to a script on a remote server --><script is:inline src="https://my-analytics.com/script.js"></script>Patrones de script comunes
Sección titulada “Patrones de script comunes”Manejar onclick y otros eventos
Sección titulada “Manejar onclick y otros eventos”Algunos frameworks de UI utilizan una sintaxis personalizada para el manejo de eventos como onClick={...} (React/Preact) o @click="..." (Vue). Astro sigue el HTML estándar de forma más directa y no utiliza sintaxis personalizada para los eventos.
En su lugar, puedes usar addEventListener en una etiqueta <script> para manejar las interacciones del usuario.
<button class="alert">Click me!</button>
<script> // Find all buttons with the `alert` class on the page. const buttons = document.querySelectorAll('button.alert');
// Handle clicks on each button. buttons.forEach((button) => { button.addEventListener('click', () => { alert('Button was clicked!'); }); });</script>Si tienes múltiples componentes <AlertButton /> en una página, Astro no ejecutará el script varias veces. Los scripts se agrupan y solo se incluyen una vez por página. El uso de querySelectorAll asegura que este script adjunte el detector de eventos a cada botón con la clase alert que se encuentre en la página.
Componentes web con elementos personalizados
Sección titulada “Componentes web con elementos personalizados”Puedes crear tus propios elementos HTML con comportamiento personalizado utilizando el estándar de Web Components. Definir un elemento personalizado en un componente .astro te permite construir componentes interactivos sin necesidad de una biblioteca de framework de UI.
En este ejemplo, definimos un nuevo elemento HTML <astro-heart> que registra cuántas veces haces clic en el botón del corazón y actualiza la etiqueta <span> con el recuento más reciente.
<!-- Wrap the component elements in our custom element “astro-heart”. --><astro-heart> <button aria-label="Heart">💜</button> × <span>0</span></astro-heart>
<script> // Define the behavior for our new type of HTML element. class AstroHeart extends HTMLElement { connectedCallback() { let count = 0;
const heartButton = this.querySelector("button"); const countSpan = this.querySelector("span");
// Each time the button is clicked, update the count. if (heartButton && countSpan) { heartButton.addEventListener("click", () => { count++; countSpan.textContent = count.toString(); }); } } }
// Tell the browser to use our AstroHeart class for <astro-heart> elements. customElements.define("astro-heart", AstroHeart);</script>Hay dos ventajas al usar un elemento personalizado aquí:
-
En lugar de buscar en toda la página usando
document.querySelector(), puedes usarthis.querySelector(), que solo busca dentro de la instancia actual del elemento personalizado. Esto hace que sea más fácil trabajar únicamente con los hijos de una instancia de componente a la vez. -
Aunque un
<script>solo se ejecuta una vez, el navegador ejecutará el métodoconnectedCallback()de nuestro elemento personalizado cada vez que encuentre<astro-heart>en la página. Esto significa que puedes escribir código de forma segura para un componente a la vez, incluso si tienes la intención de usar este componente varias veces en una página.
Pasar variables de frontmatter a scripts
Sección titulada “Pasar variables de frontmatter a scripts”En los componentes de Astro, el código del frontmatter (entre las líneas divisorias ---) se ejecuta en el servidor y no está disponible en el navegador.
Para pasar variables del lado del servidor a los scripts del lado del cliente, almacénalas en atributos data-* en los elementos HTML. Los scripts pueden acceder a estos valores utilizando la propiedad dataset.
En este componente de ejemplo, una prop message se almacena en un atributo data-message, de modo que el elemento personalizado puede leer this.dataset.message y obtener el valor de la prop en el navegador.
---const { message = 'Welcome, world!' } = Astro.props;---
<!-- Store the message prop as a data attribute. --><astro-greet data-message={message}> <button>Say hi!</button></astro-greet>
<script> class AstroGreet extends HTMLElement { connectedCallback() { // Read the message from the data attribute. const message = this.dataset.message; const button = this.querySelector('button'); button?.addEventListener('click', () => { alert(message); }); } }
customElements.define('astro-greet', AstroGreet);</script>Ahora podemos usar nuestro componente varias veces y ser recibidos por un mensaje diferente para cada uno.
---import AstroGreet from '../components/AstroGreet.astro';---
<!-- Use the default message: “Welcome, world!” --><AstroGreet />
<!-- Use custom messages passed as a props. --><AstroGreet message="Lovely day to build components!" /><AstroGreet message="Glad you made it! 👋" />¡De hecho, esto es lo que hace Astro entre bastidores cuando pasas props a un componente escrito usando un framework de UI como React! Para componentes con una directiva client:*, Astro crea un elemento personalizado <astro-island> con un atributo props que almacena tus props del lado del servidor en la salida HTML.
Combinando scripts y frameworks de UI
Sección titulada “Combinando scripts y frameworks de UI”Es posible que los elementos renderizados por un framework de UI aún no estén disponibles cuando se ejecuta una etiqueta <script>. Si tu script también necesita manejar componentes de un framework de UI, se recomienda utilizar un elemento personalizado.