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

The Component Model

Astro component คือไฟล์ .astro ที่คุณ import และใช้ในอีกไฟล์ได้ รับ props เข้ามาแล้วคืน HTML ออกไป เพราะ render บน server component จึงเป็น function จาก props ไปเป็น markup — ไม่มี lifecycle ฝั่ง client

src/components/Card.astro
---
interface Props {
title: string;
href: string;
}
const { title, href } = Astro.props; // props มาที่ Astro.props
---
<a class="card" href={href}>
<h3>{title}</h3>
</a>

การใช้งาน:

---
import Card from '../components/Card.astro';
---
<Card title="Hello" href="/hello" />

props เข้ามาผ่าน Astro.props และคุณกำหนด type ของ props ด้วยการประกาศ interface Props ใน frontmatter — Astro ใช้ interface นี้ type-check การใช้งาน ที่นี่ไม่มี useState component รันครั้งเดียวเพื่อผลิต HTML

บ่อยครั้ง component ต้องห่อ content ที่ไม่รู้ล่วงหน้า นั่นคือหน้าที่ของ slots — markup ลูกที่คุณวางไว้ระหว่าง tag ของ component จะถูก render ตรงที่ <slot /> ปรากฏ

src/components/Panel.astro
---
const { heading } = Astro.props;
---
<section class="panel">
<h2>{heading}</h2>
<slot /> <!-- children มาตรงนี้ -->
</section>
<Panel heading="Notes">
<p>markup ตรงนี้จะไปลงใน slot</p>
</Panel>

ถ้าต้องการจุดแทรกมากกว่าหนึ่งจุด ใช้ named slots:

Layout.astro
<header><slot name="header" /></header>
<main><slot /></main> <!-- default slot -->
<footer><slot name="footer" /></footer>
<Layout>
<h1 slot="header">Title</h1>
<p>Body ไปลงใน default slot</p>
<small slot="footer">© 2026</small>
</Layout>
flowchart LR
  parent["Parent ส่ง markup
ระหว่าง tag"] --> slot["component render มัน
ที่ <slot />"]
  slot --> out["HTML ที่ประกอบแล้ว"]
Slots ให้ parent แทรก markup เข้าไปใน component

Slots คือกระดูกสันหลังของ layouts: Layout.astro นิยามเชลล์ของหน้า (head, nav, footer) พร้อม <slot /> สำหรับ body ของหน้า และทุกหน้าก็ห่อ content ของตัวเองไว้ใน layout นั้น

tag <style> ภายใน .astro component เป็น scoped ให้ component นั้นโดย default — Astro เขียน selector ใหม่เพื่อไม่ให้ style รั่วออกไปชนกับ component อื่น

<h1>Title</h1>
<style>
/* rule h1 นี้ใช้เฉพาะกับ h1 ของ component นี้ ไม่ใช่ตัวอื่นบนหน้า */
h1 { color: rebeccapurple; }
</style>

คุณได้ CSS แบบ component-local ด้วย selector ธรรมดา — ไม่มี CSS-in-JS ไม่ต้องมีพิธีตั้งชื่อแบบ BEM เมื่อคุณ อยาก ให้ rule ใช้แบบ global คุณ opt out ด้วย <style is:global> (พูดถึงในบท styles)

Astro component รับ props ของตัวเองยังไง?
slot ใช้ทำอะไร?
โดย default block `<style>` ใน .astro component มีผลที่ไหน?
คุณจะมีจุดแทรกหลายจุดใน component เดียวยังไง?