六维教程

Astro 插槽 slot

插槽解决什么问题

有时候组件的外壳固定,但中间内容不固定,比如「卡片」的边框和标题样式一样,里面却可能放文字、图片或列表,插槽就是用来接收这些「外部塞进来的内容」。

使用插槽

基础插槽

在组件模板里写 <slot />,调用方写在标签之间的内容会落到这里。

---
// src/components/Card.astro
const { title } = Astro.props;
---
<div class="card">
  <h3>{title}</h3>
  <div class="card-body">
    <slot />
  </div>
</div>

调用:

---
import Card from '../components/Card.astro';
---
<Card title="公告">
  <p>今天服务器维护。</p>
</Card>

具名插槽

一个组件可能有多个插槽位置,用 name 区分。

---
// Layout.astro
---
<div class="page">
  <header><slot name="header" /></header>
  <main><slot /></main>
  <footer><slot name="footer" /></footer>
</div>

使用具名插槽,要包一层带 slot 属性的元素。

---
import Layout from '../components/Layout.astro';
---
<Layout>
  <h1 slot="header">页面标题</h1>
  <p>这是正文</p>
  <p slot="footer">版权所有</p>
</Layout>

没有名字的 <slot /> 接收「默认插槽」内容(上面的 <p>这是正文</p>)。

插槽的兜底内容

如果调用方没提供插槽内容,可以写一段默认内容。

<slot>
  <p>默认提示:这里暂时没有内容</p>
</slot>

在脚本里读取插槽

有时需要在组件脚本里判断「调用方有没有传某个插槽」,用 Astro.slots.has

---
const hasHeader = Astro.slots.has('header'); // 判断调用方是否传了名为 header 的插槽
---
{hasHeader && <div class="has-header" />}

还可以用 Astro.slots.render 异步取出插槽的 HTML 字符串做处理。

---
const content = await Astro.slots.render('default'); // 把默认插槽的内容渲染成 HTML 字符串
---
<div set:html={content} />

插槽与 Props 的配合

插槽负责「结构/内容」,Props 负责「配置/数据」,两者经常一起用,比如卡片用 Props 控制标题,用插槽装正文。

上一篇
Astro 列表渲染
下一篇
Astro 客户端脚本