跳转到内容

模板表达式参考

Astro 组件语法是 HTML 的超集。该语法旨在让任何有 HTML 或 JSX 编写经验的人都感到熟悉,并增加了对组件和 JavaScript 表达式的支持。

你可以在 Astro 组件的两个代码栅栏(---)之间的 frontmatter 组件脚本中定义本地 JavaScript 变量。然后,你可以使用类 JSX 表达式将这些变量注入到组件的 HTML 模板中!

可以使用大括号语法将局部变量添加到 HTML 中

src/components/Variables.astro
---
const name = "Astro";
---
<div>
<h1>Hello {name}!</h1> <!-- Outputs <h1>Hello Astro!</h1> -->
</div>

局部变量可用于大括号中,以将属性值传递给 HTML 元素和组件

src/components/DynamicAttributes.astro
---
const name = "Astro";
---
<h1 class={name}>Attribute expressions are supported</h1>
<MyComponent templateLiteralNameAttribute={`MyNameIs${name}`} />

局部变量可用于类 JSX 函数中,以生成动态的 HTML 元素

src/components/DynamicHtml.astro
---
const items = ["Dog", "Cat", "Platypus"];
---
<ul>
{items.map((item) => (
<li>{item}</li>
))}
</ul>

Astro 可以使用 JSX 逻辑运算符和三元表达式来条件性地显示 HTML。

src/components/ConditionalHtml.astro
---
const visible = true;
---
{visible && <p>Show me!</p>}
{visible ? <p>Show me!</p> : <p>Else show me!</p>}

你还可以通过将 HTML 标签名分配给变量或通过组件导入重新分配来使用动态标签

src/components/DynamicTags.astro
---
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}`} 添加到你的元素上。

Astro 支持 <> </> 表示法,并提供了一个内置的 <Fragment /> 组件。当添加set:* 指令来注入 HTML 字符串时,该组件可用于避免使用包装器元素。

以下示例使用 <Fragment /> 组件渲染段落文本

src/components/SetHtml.astro
---
const htmlString = '<p>Raw HTML content</p>';
---
<Fragment set:html={htmlString} />

Astro 组件语法是 HTML 的超集。它旨在让任何有 HTML 或 JSX 经验的人都感到熟悉,但 .astro 文件和 JSX 之间有几个关键区别。

在 Astro 中,所有 HTML 属性都使用标准的 kebab-case 格式,而不是 JSX 中使用的 camelCase。这甚至适用于 class,而 React 不支持该属性。

example.astro
<div className="box" dataValue="3" />
<div class="box" data-value="3" />

一个 Astro 组件模板可以渲染多个元素,无需像 JavaScript 或 JSX 那样将所有内容都包装在单个 <div><> 中。

src/components/RootElements.astro
---
// 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 风格的注释。

example.astro
---
---
<!-- HTML comment syntax is valid in .astro files -->
{/* JS comment syntax is also valid */}

Astro.slots 包含用于修改 Astro 组件插槽子元素的实用函数。

类型: (slotName: string) => boolean

你可以使用 Astro.slots.has() 检查是否存在特定插槽名称的内容。当你想包装插槽内容,但又只希望在插槽被使用时才渲染包装元素时,这会很有用。

src/pages/index.astro
---
---
<slot />
{Astro.slots.has('more') && (
<aside>
<h2>More</h2>
<slot name="more" />
</aside>
)}

类型: (slotName: string, args?: any[]) => Promise<string>

你可以使用 Astro.slots.render() 异步地将插槽内容渲染为 HTML 字符串。

---
const html = await Astro.slots.render('default');
---
<Fragment set:html={html} />

Astro.slots.render() 可选地接受第二个参数:一个参数数组,该数组将转发给任何函数子代。这对于自定义实用组件很有用。

例如,这个 <Shout /> 组件将其 message prop 转换为大写,并将其传递给默认插槽

src/components/Shout.astro
---
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 参数

src/pages/index.astro
---
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 组件递归调用。此行为允许你通过在组件模板中使用 <Astro.self> 从其内部渲染 Astro 组件。这有助于迭代大型数据存储和嵌套数据结构。

NestedList.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>
贡献 社区 赞助