ข้ามไปยังเนื้อหา

Slots

React ส่ง children ผ่าน prop ชื่อ children ส่วน Astro ใช้ <slot /> ที่เป็นแนวคิดของ Web Component ที่สร้างไว้ใน template เลย ผลลัพธ์เหมือนกัน: parent เป็นคนตัดสินใจว่าจะใส่อะไรเข้าไปข้างใน ส่วน component เป็นคนตัดสินใจว่าจะวางเนื้อหานั้นไว้ตรงไหน

React
// Card.jsx
export default function Card({ children }) {
return (
<div className="card">
{children}
</div>
);
}
// Usage:
// <Card>
// <h2>Title</h2>
// <p>Body text</p>
// </Card>
Astro
---
// Card.astro
---
<div class="card">
<slot />
</div>
<!-- Usage:
<Card>
<h2>Title</h2>
<p>Body text</p>
</Card>
-->

ไม่ต้องประกาศ prop ใด ๆ — <slot /> จะรับ children ที่ส่งเข้ามาให้ component โดยอัตโนมัติ ถ้าไม่มี children ถูกส่งเข้ามา slot จะไม่ render อะไรเลย (คุณสามารถใส่ fallback content ไว้ระหว่าง tag ของ slot ได้: <slot>Default content</slot>)

React ไม่มี named slot ในตัว pattern ที่ใช้กันทั่วไปคือ render props, compound component หรือ prop แยกอย่าง header={<H1 />} ส่วน Astro มี named slot แบบ first-class

ใน นิยามของ component ให้วาง <slot name="header" /> ตรงตำแหน่งที่คุณต้องการให้ content ของ header ปรากฏ

ใน การใช้งาน component ให้เพิ่ม slot="header" ลงใน child element ใด ๆ เพื่อส่งไปยัง slot นั้น

React
// Layout.jsx — React named-slot workaround
export default function Layout({ header, sidebar, children }) {
return (
<div className="layout">
<header>{header}</header>
<aside>{sidebar}</aside>
<main>{children}</main>
</div>
);
}
// Usage:
// <Layout
// header={<nav>Nav here</nav>}
// sidebar={<ul>Links</ul>}
// >
// <p>Main content</p>
// </Layout>
Astro
---
// Layout.astro
---
<div class="layout">
<header><slot name="header" /></header>
<aside><slot name="sidebar" /></aside>
<main><slot /></main>
</div>
<!-- Usage:
<Layout>
<nav slot="header">Nav here</nav>
<ul slot="sidebar">Links</ul>
<p>Main content</p>
</Layout>
-->
Astro
---
// No frontmatter needed for this demo
---
<html lang="en">
  <head><meta charset="utf-8" /><title>Slots demo</title></head>
  <body style="font-family:sans-serif;padding:2rem;max-width:600px;margin:auto">
    <style>
      .card { border:1px solid #e2e8f0; border-radius:8px; overflow:hidden; }
      .card header { background:#6366f1; color:#fff; padding:1rem; }
      .card main { padding:1rem; }
      .card footer { background:#f8fafc; padding:.75rem 1rem; font-size:.875rem; color:#64748b; }
    </style>

    <!-- Inline component demo using an HTML template pattern -->
    <div class="card">
      <header>
        <h2>Named Slots</h2>
      </header>
      <main>
        <p>The default slot receives children with no slot attribute.</p>
        <p>Named slots receive children tagged with slot="name".</p>
      </main>
      <footer>No JavaScript required.</footer>
    </div>
  </body>
</html>
ตัวเทียบเท่าใน Astro ของ prop `{children}` ของ React คืออะไร?
คุณจะส่ง child element ไปยัง named slot ชื่อ 'header' ใน Astro ได้อย่างไร?
อะไรจะถูก render ถ้าไม่มีอะไรถูกส่งเข้าไปยัง `<slot>Fallback text</slot>`?