模板表达式参考
Astro 组件语法是 HTML 的超集。该语法旨在让任何有 HTML 或 JSX 编写经验的人都感到熟悉,并增加了对组件和 JavaScript 表达式的支持。
类 JSX 表达式
标题为“类 JSX 表达式”的部分你可以在 Astro 组件的两个代码栅栏(---
)之间的 frontmatter 组件脚本中定义本地 JavaScript 变量。然后,你可以使用类 JSX 表达式将这些变量注入到组件的 HTML 模板中!
使用这种方法,你可以包含在 frontmatter 中计算的动态值。但一旦包含,这些值就不是响应式的,永远不会改变。Astro 组件是仅在渲染步骤中运行一次的模板。
有关Astro 和 JSX 之间的区别的更多示例,请参见下文。
可以使用大括号语法将局部变量添加到 HTML 中
---const name = "Astro";---<div> <h1>Hello {name}!</h1> <!-- Outputs <h1>Hello Astro!</h1> --></div>
动态属性
标题为“动态属性”的部分局部变量可用于大括号中,以将属性值传递给 HTML 元素和组件
---const name = "Astro";---<h1 class={name}>Attribute expressions are supported</h1>
<MyComponent templateLiteralNameAttribute={`MyNameIs${name}`} />
HTML 属性将被转换为字符串,因此无法将函数和对象传递给 HTML 元素。例如,你不能在 Astro 组件中为 HTML 元素分配事件处理程序
---function handleClick () { console.log("button clicked!");}---<!-- ❌ This doesn't work! ❌ --><button onClick={handleClick}>Nothing will happen when you click me!</button>
相反,应使用客户端脚本来添加事件处理程序,就像在原生 JavaScript 中一样
------<button id="button">Click Me</button><script> function handleClick () { console.log("button clicked!"); } document.getElementById("button").addEventListener("click", handleClick);</script>
动态 HTML
标题为“动态 HTML”的部分局部变量可用于类 JSX 函数中,以生成动态的 HTML 元素
---const items = ["Dog", "Cat", "Platypus"];---<ul> {items.map((item) => ( <li>{item}</li> ))}</ul>
Astro 可以使用 JSX 逻辑运算符和三元表达式来条件性地显示 HTML。
---const visible = true;---{visible && <p>Show me!</p>}
{visible ? <p>Show me!</p> : <p>Else show me!</p>}
动态标签
标题为“动态标签”的部分你还可以通过将 HTML 标签名分配给变量或通过组件导入重新分配来使用动态标签
---import MyComponent from "./MyComponent.astro";const Element = 'div'const Component = MyComponent;---<Element>Hello!</Element> <!-- renders as <div>Hello!</div> --><Component /> <!-- renders as <MyComponent /> -->
使用动态标签时
-
变量名必须大写。例如,使用
Element
,而不是element
。否则,Astro 会尝试将你的变量名渲染为字面上的 HTML 标签。 -
不支持 Hydration 指令。当使用
client:*
Hydration 指令时,Astro 需要知道为生产环境打包哪些组件,而动态标签模式会阻止这种情况发生。 -
不支持 `define:vars` 指令。如果无法用额外的元素(例如
<div>
)包裹子元素,那么可以手动将style={`--myVar:${value}`}
添加到你的元素上。
片段 (Fragments)
标题为“片段 (Fragments)”的部分Astro 支持 <> </>
表示法,并提供了一个内置的 <Fragment />
组件。当添加set:*
指令来注入 HTML 字符串时,该组件可用于避免使用包装器元素。
以下示例使用 <Fragment />
组件渲染段落文本
---const htmlString = '<p>Raw HTML content</p>';---<Fragment set:html={htmlString} />
Astro 和 JSX 之间的区别
标题为“Astro 和 JSX 之间的区别”的部分Astro 组件语法是 HTML 的超集。它旨在让任何有 HTML 或 JSX 经验的人都感到熟悉,但 .astro
文件和 JSX 之间有几个关键区别。
在 Astro 中,所有 HTML 属性都使用标准的 kebab-case
格式,而不是 JSX 中使用的 camelCase
。这甚至适用于 class
,而 React 不支持该属性。
<div className="box" dataValue="3" /><div class="box" data-value="3" />
多个元素
标题为“多个元素”的部分一个 Astro 组件模板可以渲染多个元素,无需像 JavaScript 或 JSX 那样将所有内容都包装在单个 <div>
或 <>
中。
---// 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>
在 Astro 中,你可以使用标准的 HTML 注释或 JavaScript 风格的注释。
------<!-- HTML comment syntax is valid in .astro files -->{/* JS comment syntax is also valid */}
HTML 风格的注释将包含在浏览器的 DOM 中,而 JS 风格的注释则会被跳过。如果要留下待办事项信息或其他仅用于开发的解释,你可能希望改用 JavaScript 风格的注释。
组件工具
标题为“组件工具”的部分Astro.slots
标题为“Astro.slots”的部分Astro.slots
包含用于修改 Astro 组件插槽子元素的实用函数。
Astro.slots.has()
标题为“Astro.slots.has()”的部分类型: (slotName: string) => boolean
你可以使用 Astro.slots.has()
检查是否存在特定插槽名称的内容。当你想包装插槽内容,但又只希望在插槽被使用时才渲染包装元素时,这会很有用。
------<slot />
{Astro.slots.has('more') && ( <aside> <h2>More</h2> <slot name="more" /> </aside>)}
Astro.slots.render()
标题为“Astro.slots.render()”的部分类型: (slotName: string, args?: any[]) => Promise<string>
你可以使用 Astro.slots.render()
异步地将插槽内容渲染为 HTML 字符串。
---const html = await Astro.slots.render('default');---<Fragment set:html={html} />
这适用于高级用例!在大多数情况下,使用 <slot />
元素渲染插槽内容会更简单。
Astro.slots.render()
可选地接受第二个参数:一个参数数组,该数组将转发给任何函数子代。这对于自定义实用组件很有用。
例如,这个 <Shout />
组件将其 message
prop 转换为大写,并将其传递给默认插槽
---const message = Astro.props.message.toUpperCase();let html = '';if (Astro.slots.has('default')) { html = await Astro.slots.render('default', [message]);}---<Fragment set:html={html} />
作为 <Shout />
子元素传递的回调函数将接收到全大写的 message
参数
---import Shout from "../components/Shout.astro";---<Shout message="slots!"> {(message) => <div>{message}</div>}</Shout>
<!-- renders as <div>SLOTS!</div> -->
回调函数可以通过带有 slot
属性的包装 HTML 元素标签传递给具名插槽。此元素仅用于将回调传输到具名插槽,不会被渲染到页面上。
<Shout message="slots!"> <fragment slot="message"> {(message) => <div>{message}</div>} </fragment></Shout>
使用标准的 HTML 元素作为包装标签,或任何不会被解释为组件的小写标签(例如 <fragment>
而不是 <Fragment />
)。不要使用 HTML 的 <slot>
元素,因为它将被解释为一个 Astro 插槽。
Astro.self
标题为“Astro.self”的部分Astro.self
允许 Astro 组件递归调用。此行为允许你通过在组件模板中使用 <Astro.self>
从其内部渲染 Astro 组件。这有助于迭代大型数据存储和嵌套数据结构。
---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>
然后可以像这样使用该组件
---import NestedList from './NestedList.astro';---<NestedList items={['A', ['B', 'C'], 'D']} />
并将渲染出如下的 HTML
<ul class="nested-list"> <li>A</li> <li> <ul class="nested-list"> <li>B</li> <li>C</li> </ul> </li> <li>D</li></ul>