Astro Component:script 與 template 兩段結構

Astro 專案的基本組成單位。關鍵特性:HTML-only template,沒有 client-side runtime——預設不在瀏覽器渲染,HTML 在 build 時就產生好。

一個 component 分成兩段:上方 --- 圍起來的 script(在 build 時執行,可以直接 await fetch 私有 API 或資料庫),下方的 template

---
import SomeAstroComponent from '../components/SomeAstroComponent.astro';
import SomeReactComponent from '../components/SomeReactComponent.jsx';
import someData from '../data/pokemon.json';
 
// Access passed-in component props, like `<X title="Hello, World" />`
const { title } = Astro.props;
// Fetch external data, even from a private API or database
const data = await fetch('SOME_SECRET_API_URL/users').then(r => r.json());
---
<!-- Your template here! -->

Props

Define Props in component script block

---
interface Props {
	title: string;
	body: string;
	href: string;
}
 
const { href, title, body } = Astro.props;
---

Assign Default value to props

---
const { greeting = "Hello", name = "Astronaut" } = Astro.props;
---
<h2>{greeting}, {name}!</h2>

Slot

use <slot/> to inject html to component

// children component
---
---
  <h1>
    <slot/>
  </h1>
  
 
// parent component
---
---
  <Children>
    <span>test</span>
  </Children>

and we can pass name for different slot

// custome component
---
---
  <div>
    <slot/>
    <slot name='second'/>
  </div>
---
  import Custome from './custom.astro'
---
  <Custom>
    <span> one </span>
    <span slot='second'> two </span>
    <span> three </span>
  </Custom>

image 18.png

you can setting default slot

---
  
---
  <slot>
    <p>This is my fallback content, if there is no child passed into slot</p>
  </slot>

by default slot will use HTML div to wrap, but we can use Fragment to cancel wrap

---
// Create a custom table with named slot placeholders for head and body content
---
<table class="bg-white">
  <thead class="sticky top-0 bg-white"><slot name="header"/></thead>
  <tbody class="[&_tr:nth-child(odd)]:bg-gray-100"><slot name="body"/></tbody>
</table>
---
import CustomTable from './CustomTable.astro';
---
<CustomTable>
  <Fragment slot="header"> <!-- pass table header -->
    <tr><th>Product name</th><th>Stock units</th></tr>
  </Fragment>
 
  <Fragment slot="body"> <!-- pass table body -->
    <tr><td>Flip-flops</td><td>64</td></tr>
    <tr><td>Boots</td><td>32</td></tr>
    <tr><td>Sneakers</td><td class="text-red-500">0</td></tr>
  </Fragment>
</CustomTable>