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 控制标题,用插槽装正文。