Referencia de expresiones de plantilla
La sintaxis de componentes de Astro es un superconjunto de HTML. La sintaxis fue diseñada para sentirse familiar para cualquiera con experiencia escribiendo HTML o JSX, y añade soporte para incluir componentes y expresiones JavaScript.
Expresiones tipo JSX
Sección titulada “Expresiones tipo JSX”Puedes definir variables JavaScript locales dentro del script del frontmatter del componente entre las dos vallas de código (---) de un componente de Astro. Luego puedes inyectar estas variables en la plantilla HTML del componente usando expresiones tipo JSX!
Usando este enfoque, puedes incluir valores dinámicos que son calculados en el frontmatter. Pero una vez incluidos, estos valores no son reactivos y nunca cambiarán. Los componentes de Astro son plantillas que se ejecutan solo una vez, durante el paso de renderizado.
Mira a continuación más ejemplos de diferencias entre Astro y JSX.
Variables
Sección titulada “Variables”Las variables locales pueden añadirse al HTML usando la sintaxis de llaves:
---const name = "Astro";---<div> <h1>Hello {name}!</h1> <!-- Outputs <h1>Hello Astro!</h1> --></div>Atributos dinámicos
Sección titulada “Atributos dinámicos”Las variables locales pueden usarse entre llaves para pasar valores de atributos tanto a elementos HTML como a componentes:
---const name = "Astro";---<h1 class={name}>Attribute expressions are supported</h1>
<MyComponent templateLiteralNameAttribute={`MyNameIs${name}`} />Los atributos HTML se convertirán a strings, por lo que no es posible pasar funciones y objetos a elementos HTML. Por ejemplo, no puedes asignar un event handler a un elemento HTML en un componente de Astro:
---function handleClick () { console.log("button clicked!");}---<!-- ❌ This doesn't work! ❌ --><button onClick={handleClick}>Nothing will happen when you click me!</button>En su lugar, usa un script del lado del cliente para añadir el event handler, como harías en JavaScript vanilla:
------<button id="button">Click Me</button><script> function handleClick () { console.log("button clicked!"); } document.getElementById("button").addEventListener("click", handleClick);</script>HTML dinámico
Sección titulada “HTML dinámico”Las variables locales pueden usarse en funciones tipo JSX para producir elementos HTML generados dinámicamente:
---const items = ["Dog", "Cat", "Platypus"];---<ul> {items.map((item) => ( <li>{item}</li> ))}</ul>Astro puede mostrar HTML condicionalmente usando operadores lógicos JSX y expresiones ternarias.
---const visible = true;---{visible && <p>Show me!</p>}
{visible ? <p>Show me!</p> : <p>Else show me!</p>}Tags dinámicos
Sección titulada “Tags dinámicos”También puedes usar tags dinámicos asignando un nombre de etiqueta HTML a una variable o con una reasignación de import de componente:
---import MyComponent from "./MyComponent.astro";const Element = 'div'const Component = MyComponent;---<Element>Hello!</Element> <!-- renders as <div>Hello!</div> --><Component /> <!-- renders as <MyComponent /> -->Al usar tags dinámicos:
-
Los nombres de variables deben ir en mayúscula. Por ejemplo, usa
Element, noelement. De lo contrario, Astro intentará renderizar el nombre de tu variable como una etiqueta HTML literal. -
Las directivas de hidratación no son soportadas. Al usar
directivas de hidratación client:*, Astro necesita saber qué componentes empaquetar para producción, y el patrón de tag dinámico impide que esto funcione. -
La directiva define:vars no es soportada. Si no puedes envolver los hijos con un elemento extra (ej.
<div>), entonces puedes añadir manualmente unstyle={`--myVar:${value}`}a tu Element.
Fragmentos
Sección titulada “Fragmentos”Astro soporta la notación <> </> y también proporciona un componente integrado <Fragment />. Este componente puede ser útil para evitar elementos contenedores al añadir directivas set:* para inyectar un string HTML.
El siguiente ejemplo renderiza texto de párrafo usando el componente <Fragment />:
---const htmlString = '<p>Raw HTML content</p>';---<Fragment set:html={htmlString} />Diferencias entre Astro y JSX
Sección titulada “Diferencias entre Astro y JSX”La sintaxis de componentes de Astro es un superconjunto de HTML. Fue diseñada para sentirse familiar para cualquiera con experiencia en HTML o JSX, pero hay un par de diferencias clave entre los archivos .astro y JSX.
Atributos
Sección titulada “Atributos”En Astro, usas el formato estándar kebab-case para todos los atributos HTML en lugar del camelCase usado en JSX. Esto incluso funciona para class, que no es soportado por React.
<div className="box" dataValue="3" /><div class="box" data-value="3" />Múltiples elementos
Sección titulada “Múltiples elementos”Una plantilla de componente de Astro puede renderizar múltiples elementos sin necesidad de envolver todo en un único <div> o <>, a diferencia de JavaScript o JSX.
---// Template with multiple elements---<p>No need to wrap elements in a single containing element.</p><p>Astro supports multiple root elements in a template.</p>Comentarios
Sección titulada “Comentarios”En Astro, puedes usar comentarios HTML estándar o comentarios estilo JavaScript.
------<!-- HTML comment syntax is valid in .astro files -->{/* JS comment syntax is also valid */}Los comentarios estilo HTML se incluirán en el DOM del navegador, mientras que los de JS se omitirán. Para dejar mensajes TODO u otras explicaciones solo de desarrollo, puede que quieras usar comentarios estilo JavaScript en su lugar.
Utilidades de componentes
Sección titulada “Utilidades de componentes”Astro.slots
Sección titulada “Astro.slots”Astro.slots contiene funciones utilitarias para modificar los hijos slotted de un componente de Astro.
Astro.slots.has()
Sección titulada “Astro.slots.has()”Type: (slotName: string) => boolean
Puedes verificar si existe contenido para un nombre de slot específico con Astro.slots.has(). Esto puede ser útil cuando quieres envolver contenidos de slot pero solo quieres renderizar los elementos contenedores cuando el slot está siendo usado.
------<slot />
{Astro.slots.has('more') && ( <aside> <h2>More</h2> <slot name="more" /> </aside>)}Astro.slots.render()
Sección titulada “Astro.slots.render()”Type: (slotName: string, args?: any[]) => Promise<string>
Puedes renderizar asincrónicamente el contenido de un slot a un string de HTML usando Astro.slots.render().
---const html = await Astro.slots.render('default');---<Fragment set:html={html} />Esto es para casos de uso avanzados! En la mayoría de las circunstancias, es más simple renderizar el contenido del slot con el elemento <slot />.
Astro.slots.render() acepta opcionalmente un segundo argumento: un array de parámetros que se reenviarán a cualquier función hija. Esto puede ser útil para componentes utilitarios personalizados.
Por ejemplo, este componente <Shout /> convierte su prop message a mayúsculas y la pasa al slot por defecto:
---const message = Astro.props.message.toUpperCase();let html = '';if (Astro.slots.has('default')) { html = await Astro.slots.render('default', [message]);}---<Fragment set:html={html} />Una función callback pasada como hija de <Shout /> recibirá el parámetro message en mayúsculas:
---import Shout from "../components/Shout.astro";---<Shout message="slots!"> {(message) => <div>{message}</div>}</Shout>
<!-- renders as <div>SLOTS!</div> -->Las funciones callback pueden pasarse a slots nombrados dentro de una etiqueta de elemento HTML contenedor con un atributo slot. Este elemento solo se usa para transferir el callback a un slot nombrado y no se renderizará en la página.
<Shout message="slots!"> <fragment slot="message"> {(message) => <div>{message}</div>} </fragment></Shout>Usa un elemento HTML estándar para la etiqueta contenedora o cualquier etiqueta en minúsculas (ej. <fragment> en lugar de <Fragment />) que no será interpretada como un componente. No uses el elemento HTML <slot> ya que será interpretado como un slot de Astro.
Astro.self
Sección titulada “Astro.self”Astro.self permite que los componentes de Astro sean llamados recursivamente. Este comportamiento te permite renderizar un componente de Astro desde dentro de sí mismo usando <Astro.self> en la plantilla del componente. Esto puede ayudar a iterar sobre grandes almacenes de datos y estructuras de datos anidadas.
---const { items } = Astro.props;---<ul class="nested-list"> {items.map((item) => ( <li> <!-- If there is a nested data-structure we render `<Astro.self>` --> <!-- and can pass props through with the recursive call --> {Array.isArray(item) ? ( <Astro.self items={item} /> ) : ( item )} </li> ))}</ul>Este componente podría entonces usarse así:
---import NestedList from './NestedList.astro';---<NestedList items={['A', ['B', 'C'], 'D']} />Y renderizaría HTML así:
<ul class="nested-list"> <li>A</li> <li> <ul class="nested-list"> <li>B</li> <li>C</li> </ul> </li> <li>D</li></ul>