Saltar al contenido

Importar y componer componentes

La composición en Astro 7: importar otros componentes .astro en la valla y usarlos como etiquetas, pasar datos por props y recibirlas con Astro.props, anidar contenido mediante slots por defecto y con nombre, y ver el árbol de componentes resolverse entero en el build.

Importar y usar un componente

La composición empieza en la valla con un import, exactamente como traerías una función de otro módulo. Una vez importado, el componente se usa en la plantilla como si fuera una etiqueta HTML más, con la convención universal de que su nombre empieza por mayúscula para distinguirlo de las etiquetas nativas.

ASTRO
---import Tarjeta from '../components/Tarjeta.astro';import Cabecera from '../components/Cabecera.astro';---<Cabecera /><main>  <Tarjeta />  <Tarjeta /></main>

Ese import vive en la valla, así que sigue las reglas de la lección anterior: se resuelve en el build o en el servidor y no engrosa el bundle de cliente. Importar y usar diez componentes .astro no añade un solo byte de JavaScript a la página, porque cada uno se expande a su HTML en el momento del renderizado y desaparece como abstracción.

Pasar props

Un componente reutilizable necesita variar según el contexto, y eso se logra con props: atributos que el padre escribe en la etiqueta y el hijo recibe a través de Astro.props. La sintaxis de paso es la de los atributos HTML, con llaves para valores que no sean texto literal.

ASTRO
---// padreimport Tarjeta from '../components/Tarjeta.astro';const total = 42;---<Tarjeta titulo="Bienvenida" destacado total={total} />

En el hijo, la práctica canónica es declarar una interface Props que documente el contrato y desestructurar Astro.props, aprovechando para dar valores por defecto. Así el editor conoce qué props existen, cuáles son obligatorias y de qué tipo, y protesta si el padre se equivoca.

ASTRO
---// hijo: Tarjeta.astrointerface Props {  titulo: string;  total?: number;  destacado?: boolean;}const { titulo, total = 0, destacado = false } = Astro.props;---<article class:list={["tarjeta", { destacado }]}>  <h2>{titulo}</h2>  <p>Total: {total}</p></article>

Los datos fluyen en una sola dirección: del padre al hijo. El hijo lee sus props pero no las modifica ni avisa al padre de cambios, porque no hay cambios que comunicar —todo ocurre una vez, en el build—. Esta unidireccionalidad no es una limitación que sortear, sino el reflejo natural de un modelo donde el árbol se calcula de golpe y no vuelve a moverse.

Cuando reenvías un conjunto de props a un hijo sin nombrarlas una a una, el operador de propagación las expande igual que en una llamada de función. Es útil para componentes de envoltura que pasan casi todo hacia abajo:

ASTRO
---import Enlace from '../components/Enlace.astro';const atributos = { href: "/blog", class: "destacado" };---<Enlace {...atributos}>Ir al blog</Enlace>

El hijo recibe href y class en su Astro.props como si las hubieras escrito una por una. Con moderación, la propagación reduce la repetición; en exceso, oscurece qué recibe de verdad el hijo, así que resérvala para casos claros de reenvío.

Anidar: slots

Las props pasan datos, pero a veces quieres pasar marcado: envolver contenido dentro de un componente. Para eso está el slot, un hueco en la plantilla del hijo donde Astro inyecta lo que el padre escribió entre las etiquetas de apertura y cierre. Es el mecanismo que permite escribir componentes de envoltura —tarjetas, layouts, diálogos— que no saben de antemano qué contendrán.

ASTRO
---// Panel.astrointerface Props { titulo: string; }const { titulo } = Astro.props;---<section class="panel">  <h2>{titulo}</h2>  <slot /></section>
ASTRO
---import Panel from '../components/Panel.astro';---<Panel titulo="Resumen">  <p>Este párrafo aterriza en el slot del panel.</p></Panel>

Cuando necesitas varios huecos distintos, usas slots con nombre. El hijo declara <slot name="pie" /> y el padre dirige contenido a ese hueco con el atributo slot="pie". Todo lo que no lleve nombre cae en el slot por defecto. Un slot puede además ofrecer contenido de reserva entre sus etiquetas, que se muestra solo si el padre no llena ese hueco.

ASTRO
<!-- en el hijo --><footer><slot name="pie">Sin pie definido</slot></footer><!-- en el padre --><Panel titulo="Ventas">  <p>Contenido principal.</p>  <span slot="pie">Actualizado hoy</span></Panel>

El árbol de composición

Componer produce un árbol: una página usa un layout, el layout usa una cabecera y un pie, la cabecera usa un logo. Astro recorre ese árbol de arriba abajo, renderiza cada nodo a su HTML, encaja las props y los slots, y aplana todo en un único documento. No queda ninguna huella de la estructura de componentes en la salida: donde tú viste Tarjeta, el navegador ve un article.

Que el árbol se aplane en el build tiene un efecto secundario agradable: el HTML final es limpio. No aparecen envoltorios artificiales, ni atributos de framework, ni marcadores de componente; solo las etiquetas semánticas que escribiste dentro de cada pieza. El navegador —y también el motor de búsqueda— reciben un documento que parece escrito a mano, aunque lo compusieras con decenas de componentes anidados.