Scripts y manejo de eventos
Puedes agregar interactividad a tus componentes de Astro sin usar un framework de interfaz de usuario como React, Svelte, Vue, etc. usando las etiquetas estándar HTML <script>
. Esto te permite enviar JavaScript para ejecutar en el navegador y agregar funcionalidad a tus componentes de Astro.
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.
Por defecto, Astro procesa y empaqueta las etiquetas <script>
, agregando soporte para importar módulos npm, escribir TypeScript y más.
Usando <script>
en Astro
En archivos .astro
, puedes agregar JavaScript del lado del cliente agregando una (o más) etiquetas <script>
.
En este ejemplo, agregar el componente <Hello />
a una página registrará un mensaje en la consola del navegador.
Procesamiento de scripts
De forma predeterminada, las etiquetas <script>
son procesadas por Astro.
- Cualquier importación se empaquetará, permitiéndote importar archivos locales o módulos de Node.
- El script procesado se insertará en el
<head>
de tu página contype="module"
. - TypeScript es totalmente compatible, incluyendo la importación de archivos TypeScript.
- Si tu componente se usa varias veces en una página, el script solo se incluirá una vez.
El atributo type="module"
hace que el navegador trate el script como un módulo de JavaScript. Esto tiene varios beneficios de rendimiento:
- El renderizado no se bloquea. El navegador continúa procesando el resto del HTML mientras el script del módulo y sus dependencias se cargan.
- El navegador espera a que se procese el HTML antes de ejecutar los scripts del módulo. No es necesario escuchar el evento “load”.
- Los atributos
async
ydefer
no son necesarios. Los scripts del módulo siempre se diferirán.
::: nota
El atributo async
es valioso para scripts normales porque evita que bloqueen el renderizado. Sin embargo, los scripts del módulo ya tienen este comportamiento. Agregar async
a un script del módulo hará que se ejecute antes de que la página se haya cargado por completo. Probablemente no es lo que deseas.
:::
Optar por no procesar
Para evitar que Astro procese un script, agregue la directiva is:inline
.
Astro no procesará tus etiquetas de script en algunas situaciones. En particular, al agregar type="module"
o cualquier atributo que no sea src
a una etiqueta <script>
hará que Astro trate la etiqueta como si tuviera una directiva is:inline
. Lo mismo será cierto cuando el script esté escrito en una expresión JSX.
📚 Consulta nuestra página de referencia de directivas para obtener más información sobre las directivas disponibles en las etiquetas <script>
.
Incluye 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
Cuándo usar esto: Cuando tu script se encuentra dentro de src/
.
Astro empaquetará, optimizará y agregará estos scripts a la página por ti, siguiendo sus reglas de procesado.
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.
Patrones comunes de script
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.
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.
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.
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étodoconstructor()
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.
📚 Puedes aprender más sobre elementos personalizaods en la guía de Componentes Web Reusables de web.dev y en la introducción de MDN a elementos personalizados.
Pasando variables frontmatter a scripts
En componentes Astro, el codigo en el frontmatter entre los cercos ---
se ejecuta en el servidor y no esta disponible en el navegador. Para mandar variables desde el servidor al cliente, necesitamos una manera de guardar nuestras variables y leerlas cuando JavaScript se ejecute en el navegador.
Una manera para hacer esto es usando atributos data-*
para guardar el valor de las variables en tu HTML. Los scripts, incluyendo elementos personalizados, pueden entonces leer estos atributos usando la propiedad de elemento dataset
una vez que tu HTML cargue en el navegador.
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.
Ahora podemos usar nuestro componente múltiples veces y ser saludados con un mensaje diferente por cada uno.
¡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.