Componentes
Los componentes de Astro son los bloques de construcción básicos de cualquier proyecto de Astro. Son componentes de plantilla de solo HTML sin tiempo de ejecución en el cliente y utilizan la extensión de archivo .astro.
Si sabes HTML, ya sabes lo suficiente para escribir tu primer componente de Astro.
Los componentes de Astro son extremadamente flexibles. Un componente de Astro puede ser tan pequeño como un fragmento de HTML, como una colección de etiquetas <meta> comunes que facilitan el trabajo con el SEO. Los componentes pueden ser elementos de interfaz de usuario reutilizables, como un encabezado o una tarjeta de perfil. Los componentes de Astro pueden incluso contener la plantilla de una página completa o, cuando se ubican en la carpeta especial src/pages/, ser una página completa en sí misma.
Lo más importante que debes saber sobre los componentes de Astro es que no se renderizan en el cliente. Se renderizan a HTML ya sea en tiempo de compilación o bajo demanda. Puedes incluir código JavaScript dentro del frontmatter de tu componente, y todo se eliminará de la página final enviada a los navegadores de tus usuarios. El resultado es un sitio más rápido, sin ninguna huella de JavaScript añadida por defecto.
Cuando tu componente de Astro necesite interactividad del lado del cliente, puedes agregar etiquetas <script> HTML estándar o componentes de frameworks de UI como "islas de cliente".
Para los componentes que necesitan renderizar contenido personalizado o dinámico, puedes posponer su renderizado en el servidor agregando una directiva de servidor. Estas "islas de servidor" renderizarán su contenido cuando esté disponible, sin retrasar la carga completa de la página.
Estructura de componentes
Sección titulada “Estructura de componentes”Un componente de Astro está compuesto por dos partes principales: el Script del componente y la Plantilla del componente. Cada parte realiza un trabajo diferente, pero juntas proporcionan un marco que es fácil de usar y lo suficientemente expresivo para manejar cualquier cosa que quieras construir.
---// Component Script (JavaScript)---<!-- Component Template (HTML + JS Expressions) -->El script del componente
Sección titulada “El script del componente”Astro utiliza una valla de código (---) para identificar el script del componente en tu componente de Astro. Si alguna vez has escrito Markdown antes, es posible que ya estés familiarizado con un concepto similar llamado frontmatter. La idea de Astro de un script de componente se inspiró directamente en este concepto.
Puedes usar el script del componente para escribir cualquier código de JavaScript que necesites para renderizar tu plantilla. Esto puede incluir:
- importar otros componentes de Astro
- importar otros componentes de frameworks, como React
- importar datos, como un archivo JSON
- obtener contenido de una API o base de datos
- crear variables a las que harás referencia en tu plantilla
---import SomeAstroComponent from '../components/SomeAstroComponent.astro';import SomeReactComponent from '../components/SomeReactComponent.jsx';import someData from '../data/pokemon.json';
// Access passed-in component props, like `<X title="Hello, World" />`const { title } = Astro.props;
// Fetch external data, even from a private API or databaseconst data = await fetch('SOME_SECRET_API_URL/users').then(r => r.json());---<!-- Your template here! -->La valla de código (code fence) está diseñada para garantizar que el JavaScript que escribas en ella esté "cercado". No se escapará a tu aplicación frontend ni caerá en manos de tus usuarios. Puedes escribir código de forma segura aquí que sea costoso o sensible (como una llamada a tu base de datos privada) sin preocuparte de que termine en el navegador de tu usuario.
El script del componente de Astro es TypeScript, lo que te permite agregar sintaxis adicional a JavaScript para herramientas de edición y comprobación de errores.
La plantilla del componente
Sección titulada “La plantilla del componente”La plantilla del componente está debajo de la valla de código y determina la salida HTML de tu componente.
Si escribes HTML simple aquí, tu componente renderizará ese HTML en cualquier página de Astro en la que se importe y use.
Sin embargo, la sintaxis de la plantilla del componente de Astro también admite expresiones de JavaScript, etiquetas <style> y <script> de Astro, componentes importados y directivas especiales de Astro. Los datos y valores definidos en el script del componente se pueden usar en la plantilla del componente para producir HTML creado dinámicamente.
---// Your component script here!import Banner from '../components/Banner.astro';import Avatar from '../components/Avatar.astro';import ReactPokemonComponent from '../components/ReactPokemonComponent.jsx';const myFavoritePokemon = [/* ... */];const { title } = Astro.props;---<!-- HTML comments supported! -->{/* JS comment syntax is also valid! */}
<Banner /><h1>Hello, world!</h1>
<!-- Use props and other variables from the component script: --><p>{title}</p>
<!-- Delay component rendering and provide fallback loading content: --><Avatar server:defer> <svg slot="fallback" class="generic-avatar" transition:name="avatar">...</svg></Avatar>
<!-- Include other UI framework components with a `client:` directive to hydrate: --><ReactPokemonComponent client:visible />
<!-- Mix HTML with JavaScript expressions, similar to JSX: --><ul> {myFavoritePokemon.map((data) => <li>{data.name}</li>)}</ul>
<!-- Use a template directive to build class names from multiple strings or even objects! --><p class:list={["add", "dynamic", { classNames: true }]} />Diseño basado en componentes
Sección titulada “Diseño basado en componentes”Los componentes están diseñados para ser reutilizables y componibles. Puedes utilizar componentes dentro de otros componentes para construir interfaces de usuario cada vez más avanzadas. Por ejemplo, un componente Button podría usarse para crear un componente ButtonGroup:
---import Button from './Button.astro';---<div> <Button title="Button 1" /> <Button title="Button 2" /> <Button title="Button 3" /></div>Props de componentes
Sección titulada “Props de componentes”Un componente de Astro puede definir y aceptar props. Estas props luego están disponibles para la plantilla del componente para renderizar HTML. Las props están disponibles en el objeto global Astro.props en el script del frontmatter.
Aquí hay un ejemplo de un componente que recibe una prop greeting y una prop name. Ten en cuenta que las props a recibir se desestructuran del objeto global Astro.props.
---// Usage: <GreetingHeadline greeting="Howdy" name="Partner" />const { greeting, name } = Astro.props;---<h2>{greeting}, {name}!</h2>Este componente, cuando se importa y se renderiza en otros componentes, layouts o páginas de Astro, puede pasar estas props como atributos:
---import GreetingHeadline from './GreetingHeadline.astro';const name = 'Astro';---<h1>Greeting Card</h1><GreetingHeadline greeting="Hi" name={name} /><p>I hope you have a wonderful day!</p>También puedes definir tus props con TypeScript con una interfaz de tipo Props. Astro recogerá automáticamente la interfaz Props en tu frontmatter y dará advertencias/errores de tipo. A estas props también se les pueden dar valores por defecto cuando se desestructuran de Astro.props.
---interface Props { name: string; greeting?: string;}
const { greeting = "Hello", name } = Astro.props;---<h2>{greeting}, {name}!</h2>A las props del componente se les pueden asignar valores por defecto para usar cuando no se proporcione ninguno.
---const { greeting = "Hello", name = "Astronaut" } = Astro.props;---<h2>{greeting}, {name}!</h2>El elemento <slot /> es un marcador de posición para contenido HTML externo, lo que te permite inyectar (o "colocar en un slot") elementos hijos de otros archivos en la plantilla de tu componente.
Por defecto, todos los elementos hijos pasados a un componente se renderizarán en su <slot />.
A diferencia de las props, que son atributos que se pasan a un componente de Astro disponibles para su uso en todo el componente con Astro.props, los slots renderizan los elementos HTML hijos donde se escriben.
---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 /> <!-- children will go here --> <Footer /></div>---import Wrapper from '../components/Wrapper.astro';---<Wrapper title="Fred's Page"> <h2>All about Fred</h2> <p>Here is some stuff about Fred.</p></Wrapper>Este patrón es la base de un componente de layout de Astro: una página entera de contenido HTML puede ser "envuelta" con etiquetas <SomeLayoutComponent></SomeLayoutComponent> y enviada al componente para renderizarla dentro de los elementos comunes de la página definidos allí.
Astro.slots para conocer más formas de acceder y renderizar el contenido de los slots.
Slots con nombre
Sección titulada “Slots con nombre”Un componente de Astro también puede tener slots con nombre. Esto te permite pasar solo elementos HTML con el nombre de slot correspondiente a la ubicación de un slot.
Los slots se nombran usando el atributo name:
---import Header from './Header.astro';import Logo from './Logo.astro';import Footer from './Footer.astro';
const { title } = Astro.props;---<div id="content-wrapper"> <Header /> <!-- children with the `slot="after-header"` attribute will go here --> <slot name="after-header" /> <Logo /> <h1>{title}</h1> <!-- children without a `slot`, or with `slot="default"` attribute will go here --> <slot /> <Footer /> <!-- children with the `slot="after-footer"` attribute will go here --> <slot name="after-footer" /></div>Para inyectar contenido HTML en un slot en particular, usa el atributo slot en cualquier elemento hijo para especificar el nombre del slot. Todos los demás elementos hijos del componente se inyectarán en el <slot /> predeterminado (sin nombre).
---import Wrapper from '../components/Wrapper.astro';---<Wrapper title="Fred's Page"> <img src="https://my.photo/fred.jpg" slot="after-header" /> <h2>All about Fred</h2> <p>Here is some stuff about Fred.</p> <p slot="after-footer">Copyright 2022</p></Wrapper>Usa un atributo slot="my-slot" en el elemento hijo que deseas pasar a un marcador de posición <slot name="my-slot" /> correspondiente en tu componente.
Para pasar múltiples elementos HTML al marcador de posición <slot/> de un componente sin un <div> envolvente, usa el atributo slot="" en el componente <Fragment/> de Astro:
---// Create a custom table with named slot placeholders for header and body content---<table class="bg-white"> <thead class="sticky top-0 bg-white"><slot name="header" /></thead> <tbody class="[&_tr:nth-child(odd)]:bg-gray-100"><slot name="body" /></tbody></table>Inyecta múltiples filas y columnas de contenido HTML utilizando un atributo slot="" para especificar el contenido del "header" y el "body". Los elementos HTML individuales también se pueden estilar:
---import CustomTable from './CustomTable.astro';---<CustomTable> <Fragment slot="header"> <!-- pass table header --> <tr><th>Product name</th><th>Stock units</th></tr> </Fragment>
<Fragment slot="body"> <!-- pass table body --> <tr><td>Flip-flops</td><td>64</td></tr> <tr><td>Boots</td><td>32</td></tr> <tr><td>Sneakers</td><td class="text-red-500">0</td></tr> </Fragment></CustomTable>Ten en cuenta que los slots con nombre deben ser hijos inmediatos del componente. No puedes pasar slots con nombre a través de elementos anidados.
¡Los slots con nombre también se pueden pasar a componentes de frameworks de UI!
No es posible generar dinámicamente un nombre de slot de Astro, como dentro de una función map. Si se necesita esta función dentro de los componentes de un framework de UI, podría ser mejor generar estos slots dinámicos dentro del propio framework.
Contenido de respaldo para slots
Sección titulada “Contenido de respaldo para slots”Los slots también pueden renderizar contenido de respaldo. Cuando no se pasan elementos hijos coincidentes a un slot, un elemento <slot /> renderizará sus propios elementos hijos marcadores de posición.
---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>This is my fallback content, if there is no child passed into slot</p> </slot> <Footer /></div>El contenido de respaldo solo se mostrará cuando no se pasen elementos coincidentes con el atributo slot="name" a un slot con nombre.
Astro pasará un slot vacío cuando exista un elemento de slot pero no tenga contenido para pasar. El contenido de respaldo no se puede usar por defecto cuando se pasa un slot vacío. El contenido de respaldo solo se muestra cuando no se puede encontrar ningún elemento de slot.
Transferencia de slots
Sección titulada “Transferencia de slots”Los slots se pueden transferir a otros componentes. Por ejemplo, al crear layouts anidados:
------<html lang="en"> <head> <meta charset="utf-8" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <meta name="viewport" content="width=device-width" /> <meta name="generator" content={Astro.generator} /> <slot name="head" /> </head> <body> <slot /> </body></html>---import BaseLayout from './BaseLayout.astro';---<BaseLayout> <slot name="head" slot="head" /> <slot /></BaseLayout>Los slots con nombre se pueden transferir a otro componente utilizando los atributos name y slot en una etiqueta <slot />.
Ahora, los slots predeterminado y head pasados a HomeLayout se transferirán al padre BaseLayout.
---import HomeLayout from '../layouts/HomeLayout.astro';---<HomeLayout> <title slot="head">Astro</title> <h1>Astro</h1></HomeLayout>Componentes HTML
Sección titulada “Componentes HTML”Astro admite la importación y el uso de archivos .html como componentes o la colocación de estos archivos dentro del subdirectorio src/pages/ como páginas. Es posible que desees utilizar componentes HTML si estás reutilizando código de un sitio existente creado sin un framework, o si deseas asegurarte de que tu componente no tenga características dinámicas.
Los componentes HTML deben contener únicamente HTML válido y, por lo tanto, carecen de características clave de los componentes de Astro:
- No admiten frontmatter, importaciones del lado del servidor ni expresiones dinámicas.
- Cualquier etiqueta
<script>se deja sin empaquetar, tratada como si tuviera una directivais:inline. - Solo pueden hacer referencia a activos que están en la carpeta
public/.
Un elemento <slot /> dentro de un componente HTML funcionará como lo haría en un componente de Astro. Para utilizar en su lugar el elemento HTML Web Component Slot, añade is:inline a tu elemento <slot>.