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 web, como la gestión de eventos o la actualización dinámica de contenidos, sin necesidad de utilizar un framework de UI como React, Svelte o Vue. Esto evita la sobrecarga que supone enviar el JavaScript del framework y no requiere que conozcas ningún framework adicional para crear un sitio web o una aplicación con todas las funciones.
Scripts del lado del cliente
Sección titulada «Scripts del lado del cliente»Los scripts pueden ser usados para agregar event listeners, enviar datos de analítica, reproducir animaciones y todo lo que JavaScript puede hacer en la web.
Astro mejora automáticamente la etiqueta estándar HTML <script>
con empaquetado, TypeScript y mucho más. Consulta cómo procesa Astro los scripts para obtener más detalles.
<!-- src/components/ConfettiButton.astro --><button data-confetti-button>¡Celebrar!</button>
<script> // Importa desde el paquete de npm. import confetti from 'canvas-confetti';
// Encuentra nuestro componente en la página. const buttons = document.querySelectorAll('[data-confetti-button]');
// Agrega event listeners para disparar confetti cuando un botón es clickeado. buttons.forEach((button) => { button.addEventListener('click', () => confetti()); });</script>
Procesamiento de scripts
Sección titulada «Procesamiento de scripts»De forma predeterminada, Astro procesa las etiquetas <script>
que no contienen atributos (aparte de src
) de las siguientes maneras:
- Compatibilidad con TypeScript: Todos los scripts son TypeScript de forma predeterminada.
- Empaquetado de importaciones: Importa archivos locales o módulos de npm, que se empaquetaran juntos.
- Tipo de módulo: Los scripts procesados se convierten automáticamente en
type="module"
. - Deduplicación: Si un componente que contiene un
<script>
se utiliza varias veces en una página, el script solo se incluirá una vez. - Inline 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> // ¡Procesado! ¡Empaquetado! ¡TypeScript! // La importación de scripts locales y paquetes de npm funciona.</script>
Scripts no procesados
Sección titulada «Scripts no procesados»Astro no procesará una etiqueta <script>
si tiene algún atributo distinto de src
.
Puedes añadir la directiva is:inline
para excluir intencionadamente el procesamiento de un script.
<script is:inline> // Sin transformar: sin TypeScript y sin resolución de importaciones por parte de Astro. // Si se utiliza dentro de un componente, este código se duplica para cada instancia.</script>
Incluye archivos de JavaScript en tu página
Sección titulada «Incluye archivos de JavaScript en tu página»Es posible que quieras escribir tus scripts como archivos separados .js
/.ts
o necesites referenciar un script externo. Puedes hacerlo referenciándolos en una etiqueta <script>
con el atributo src
.
Importando scripts locales
Sección titulada «Importando 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.
<!-- ruta relativa al script en `src/scripts/local.js` --><script src="../scripts/local.js"></script>
<!-- también funciona para archivos TypeScript locales --><script src="./script-with-types.ts"></script>
Cargando scripts externos
Sección titulada «Cargando scripts externos»Cuando usar esto: Cuando tu archivo JavaScript se encuentra dentro de public/
o en un CDN.
Para cargar scripts fuera del directorio src/
de tu proyecto, incluye la directiva is:inline
. Este enfoque omite el procesamiento, agrupación y optimización de JavaScript que proporciona Astro cuando importa scripts como se describe anteriormente.
<!-- ruta absoluta a un script en `public/my-script.js` --><script is:inline src="/my-script.js"></script>
<!-- URL completa a un script en un servidor remoto --><script is:inline src="https://my-analytics.com/script.js"></script>
Patrones comunes de script
Sección titulada «Patrones comunes de script»Manejar onclick
y otros eventos
Sección titulada «Manejar onclick y otros eventos»Algunos frameworks usan una sintaxis especial para manejar eventos como onClick={...}
(React/Preact) o @click="..."
(Vue). Astro sigue más de cerca el estándar HTML y no usa una sintaxis especial para eventos.
En su lugar, puedes usar addEventListener
en una etiqueta <script>
para manejar interaciones de usuario.
<button class="alert">¡Haz Click!</button>
<script> // Encuentra todos los botones con la clase `alert` en la página. const buttons = document.querySelectorAll('button.alert');
// Maneja los clics en cada botón. buttons.forEach((button) => { button.addEventListener('click', () => { alert('¡El botón ha sido clickeado!'); }); });</script>
Si tienes múltiples componentes <AlertButton />
en una página, Astro no ejecutará el script múltiples veces. Los scripts son empaquetados y solo incluidos una vez en la página. Usando querySelectorAll
asegura que este script agregue el event listener a cada botón con la clase alert
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 usando el estándar de componentes Web. Definir un elemento personalizado en un componente .astro
te permite crear componentes interactivos sin necesidad de un framework.
En este ejemplo, definimos un nuevo elemento HTML <astro-heart>
que rastrea cuántas veces se hace clic en el botón del corazón y actualiza el <span>
con el último conteo.
<!-- Envuelve los elementos del componente en nuestro elemento personalizado “astro-heart”. --><astro-heart> <button aria-label="Heart">💜</button> × <span>0</span></astro-heart>
<script> // Define el comportamiento para nuestro nuevo tipo de elemento HTML. class AstroHeart extends HTMLElement { connectedCallback() { let count = 0;
const heartButton = this.querySelector('button'); const countSpan = this.querySelector('span');
// Cada vez que el button es clickeado, actualiza el contador. heartButton.addEventListener('click', () => { count++; countSpan.textContent = count.toString(); }); } }
// Dile al navegador que use nuestra clase AstroHeart para elementos <astro-heart>. customElements.define('astro-heart', AstroHeart);</script>
Hay dos ventajas de usar un elemento personalizado aqui:
-
En lugar de buscar en toda la página usando
document.querySelector()
, puedes usarthis.querySelector()
, el cual solo busca dentro de la instancia del elemento personalizado. Esto facilita el trabajo solo con los hijos de una instancia del componente a la vez. -
Aunque un
<script>
solo se ejecuta una vez, el navegador ejecutará métodoconnectedCallback()
de nuestro elemento cada vez que encuentre<astro-heart>
en la página. Esto significa que puedes escribir forma segura código para un componente a la vez, incluso si tienes la intención de utilizar este componente varias veces en una página.
Pasando variables frontmatter a scripts
Sección titulada «Pasando variables frontmatter a scripts»En componentes de Astro, el codigo en el frontmatter (entre los cercos ---
) se ejecuta en el servidor y no esta disponible en el navegador.
Para pasar variables del lado del servidor a scripts del lado del cliente, guárdalas en atributos data-*
en elementos HTML. Los scripts pueden acceder a estos valores utilizando la propiedad dataset
.
En este componente ejemplo, una propiedad message
es guardada en un atributo data-message
, para que el elemento personalizado pueda leer this.dataset.message
y obtener el valor de la propiedad en el navegador.
---const { message = '¡Bienvenido, mundo!' } = Astro.props;---
<!-- Guarda la propiedad message como un atributo data. --><astro-greet data-message={message}> <button>¡Saluda!</button></astro-greet>
<script> class AstroGreet extends HTMLElement { connectedCallback() { // Lee el mensaje del atributo data. 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 múltiples veces y ser saludados con un mensaje diferente por cada uno.
---import AstroGreet from '../components/AstroGreet.astro';---
<!-- Usa el mensaje por defecto: “¡Bienvenido, mundo!” --><AstroGreet />
<!-- Usa mensajes personalizados pasados como propiedades. --><AstroGreet message="¡Es un lindo día para diseñar componentes!" /><AstroGreet message="¡Me alegro de que lo lograras! 👋" />
¡Esto es lo que realmente hace Astro detrás de escenas cuando pasas propiedades 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 guarda tus propiedades 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 gestionar componentes de un framework de UI, se recomienda utilizar un elemento personalizado.