Astro - 基礎入門4.第四課練習題實作

更新 發佈閱讀 10 分鐘

題目

任務目標:建立一個動態的「隨機推薦」組件。

  1. 建立一個名為 RandomQuote.astro 的組件。
  2. 在該組件的 Code Fence 中,使用 fetch() 從 API 抓取一句隨機名言(例如:https://api.quotable.io/random)。
  3. 在 about.astro 頁面中,以 server:defer 的方式引入這個組件。
  4. 設定一個具備 Loading 樣式的 fallback 內容。
  5. 進階挑戰: 嘗試將原本的部落格清單頁面 blog.astro 改為混合模式——頁面頂部標題是靜態的,但文章清單改由 server:defer 渲染。

目前專案結構

📁 .astro/
📁 .vscode/
📁 node_modules/
📁 public/
└─ favicon.svg
📁 src/
├─ 📁 components/
│ ├─ DescriptionControl.jsx
│ ├─ LikeButton.jsx
│ └─ ServerTime.astro
├─ 📁 content/
│ ├─ 📁 blog/
│ │ └─ post-1.md
│ └─ config.ts
├─ 📁 layouts/
│ └─ BaseLayout.astro
└─ 📁 pages/
├─ 📁 posts/
│ └─ [id].astro
├─ about.astro
├─ blog.astro
└─ index.astro
.gitignore
astro.config.mjs
package-lock.json
package.json
README.md
tscon

1_新增 src/components/RandomQuote.astro

---
let random
try {
  const res = await fetch('https://zenquotes.io/api/random')
  const data = await res.json()
  console.log(data)
  random = data
} catch (err) {
  console.error(err)
}

// 模擬一個慢速的資料庫查詢
await new Promise((resolve) => setTimeout(resolve, 2000))
---

<div class="server-box">
  <p>伺服器隨機生成:{random[0].q}</p>
  <p>(此組件是延遲載入的 Server Island)</p>
</div>

<style>
  .server-box {
    border: 2px dashed #ff5d01;
    padding: 1rem;
    background: #fff5f0;
  }
</style>

2_修改 src/pages/about.astro

  1. 匯入 RandomQuote 物件
  2. html 區塊找一個地方放 RandomQuote
  3. <p> 沒有加 slot="fallback" 是不會顯示的喔
---
import BaseLayout from '../layouts/BaseLayout.astro'
import DescriptionControl from '../components/DescriptionControl'
import RandomQuote from '../components/RandomQuote.astro'
const pageTitle = '關於我'
const identity = {
  firstName: '小明',
  hobbies: ['reading', 'gaming', 'coding'],
}

const description =
  '這段文字旨在模擬實際使用中的描述欄位,長度超過二十個字以符合需求。'
---

<BaseLayout pageTitle={pageTitle} pageName="about">
  <h2>{identity.firstName}</h2>

  <h3>我的愛好</h3>
  <ul>
    {identity.hobbies.map((x) => <li>{x}</li>)}
  </ul>

  <h3>描述</h3>
  <DescriptionControl description={description} client:visible />

  <h3>隨機生成</h3>
  <RandomQuote server:defer>
    <p slot="fallback" class="loading">等待隨機生成....</p>
  </RandomQuote>
</BaseLayout>

3_進階挑戰

3_1 新增 src/components/PostsQuote.astro

---
import { getCollection } from 'astro:content'
import type { CollectionEntry } from 'astro:content'
const posts: CollectionEntry<'blog'>[] = await getCollection('blog')
// 模擬資料庫查詢
await new Promise((resolve) => setTimeout(resolve, 2000))
---

<ul>
  {
    posts
      .sort((a, b) => {
        const a_date = a.data.pubDate.toDateString()
        const b_date = b.data.pubDate.toDateString()
        return b_date.localeCompare(a_date)
      })
      .map((post) => (
        <li>
          <a href={`/posts/${post.id}`}>{post.data.title}</a>
          <span> - {post.data.pubDate.toLocaleDateString()} </span>
        </li>
      ))
  }
</ul>

3_2 修改 src/pages/blog.astro

---

// import { getCollection } from 'astro:content'
// import type { CollectionEntry } from 'astro:content'
import BaseLayout from '../layouts/BaseLayout.astro'
import PostsQuote from '../components/PostsQuote.astro'
const pageTitle = '我的部落格'
// const allPosts: CollectionEntry<'blog'>[] = await getCollection('blog')
---

<BaseLayout pageTitle={pageTitle}>
  <PostsQuote server:defer>
    <p slot="fallback" class="loading">文章列表載入中...</p>
  </PostsQuote>
  <!-- <ul>
    {
      allPosts
        .sort((a, b) => {
          const b_date = b.data.pubDate.toDateString()
          const a_date = a.data.pubDate.toDateString()
          return b_date.localeCompare(a_date)
        })
        .map((post) => (
          <li>
            <a href={`/posts/${post.id}`}>{post.data.title}</a>
            <span> - {post.data.pubDate.toLocaleDateString()} </span>
          </li>
        ))
    }
  </ul> -->
</BaseLayout>
留言
avatar-img
李昀瑾的沙龍
0會員
35內容數
李昀瑾的沙龍的其他內容
2026/01/11
第四課:Server Islands 與 SSR (伺服器端渲染) 在之前的課程中,我們的網站是「靜態」的。 但在真實應用中,有些內容不能是靜態的(例如:用戶登入狀態、即時庫存、或是根據地理位置推薦的內容)。 1. 核心觀念:Server Islands vs. Client Islands
2026/01/11
第四課:Server Islands 與 SSR (伺服器端渲染) 在之前的課程中,我們的網站是「靜態」的。 但在真實應用中,有些內容不能是靜態的(例如:用戶登入狀態、即時庫存、或是根據地理位置推薦的內容)。 1. 核心觀念:Server Islands vs. Client Islands
2026/01/10
第三課:Astro Islands —— 混合開發與互動性 核心觀念:預設 0 JS Astro 就像一個「大洋」,預設所有組件都是靜態的 HTML(沒有 JS)。如果你需要互動(如:彈窗、購物車、即時搜尋),你就在大洋中丟入一個「孤島 (Island)」。
2026/01/10
第三課:Astro Islands —— 混合開發與互動性 核心觀念:預設 0 JS Astro 就像一個「大洋」,預設所有組件都是靜態的 HTML(沒有 JS)。如果你需要互動(如:彈窗、購物車、即時搜尋),你就在大洋中丟入一個「孤島 (Island)」。
2026/01/10
Astro - 基礎入門3.第三課練習題實作
2026/01/10
Astro - 基礎入門3.第三課練習題實作
看更多
你可能也想看
Thumbnail
5 月將於臺北表演藝術中心映演的「2026 北藝嚴選」《海妲・蓋柏樂》,由臺灣劇團「晃晃跨幅町」製作,本文將以從舞台符號、聲音與表演調度切入,討論海妲・蓋柏樂在父權社會結構下的困境,並結合榮格心理學與馮.法蘭茲對「阿尼姆斯」與「永恆少年」原型的分析,理解女人何以走向精神性的操控、毀滅與死亡。
Thumbnail
5 月將於臺北表演藝術中心映演的「2026 北藝嚴選」《海妲・蓋柏樂》,由臺灣劇團「晃晃跨幅町」製作,本文將以從舞台符號、聲音與表演調度切入,討論海妲・蓋柏樂在父權社會結構下的困境,並結合榮格心理學與馮.法蘭茲對「阿尼姆斯」與「永恆少年」原型的分析,理解女人何以走向精神性的操控、毀滅與死亡。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
Thumbnail
這是一場從「網路連結 → 線下見面」的活動,我一開始其實有些猶豫,畢竟地點對我來說不近,加上平常在社群裡其實不太主動互動。 但因為主辦人西打誠意滿滿地邀請,甚至還提出補貼車資,最後我決定自費參加。現在回頭看,真的很值得! 場地很有感,氛圍超溫暖 一踏進場地就被暖黃的燈光包圍,小閣樓超舒適,還
Thumbnail
這是一場從「網路連結 → 線下見面」的活動,我一開始其實有些猶豫,畢竟地點對我來說不近,加上平常在社群裡其實不太主動互動。 但因為主辦人西打誠意滿滿地邀請,甚至還提出補貼車資,最後我決定自費參加。現在回頭看,真的很值得! 場地很有感,氛圍超溫暖 一踏進場地就被暖黃的燈光包圍,小閣樓超舒適,還
Thumbnail
從實際應用中學習 Python 程式設計,提升技能並建立作品集。文章提供八個循序漸進的 Python 專案範例,涵蓋檔案操作、網路爬蟲、Web 應用、自動化腳本、數據分析、遊戲開發、API 互動及應用程式部署,並附上實戰建議及學習資源。
Thumbnail
從實際應用中學習 Python 程式設計,提升技能並建立作品集。文章提供八個循序漸進的 Python 專案範例,涵蓋檔案操作、網路爬蟲、Web 應用、自動化腳本、數據分析、遊戲開發、API 互動及應用程式部署,並附上實戰建議及學習資源。
Thumbnail
網站開發專案成功的關鍵在於與客戶的有效溝通。本文分享一個成功案例,說明如何透過明確掌握專案需求、主動提供技術方案、定期回報進度、完善技術協助及建立良好客戶關係,順利完成一個中文影片學習分享網站的建置,並獲得客戶高度滿意與後續合作機會。
Thumbnail
網站開發專案成功的關鍵在於與客戶的有效溝通。本文分享一個成功案例,說明如何透過明確掌握專案需求、主動提供技術方案、定期回報進度、完善技術協助及建立良好客戶關係,順利完成一個中文影片學習分享網站的建置,並獲得客戶高度滿意與後續合作機會。
Thumbnail
Nuxt.js 是以 Vue 為基底所建構的框架,透過 Nuxt.js,我們能夠更輕鬆地開發靜態頁面 (Static Site)、操作體驗良好的單頁式網站 (SPA)、甚至是顧及 SEO 的伺服器端渲染 (SSR) 網站。
Thumbnail
Nuxt.js 是以 Vue 為基底所建構的框架,透過 Nuxt.js,我們能夠更輕鬆地開發靜態頁面 (Static Site)、操作體驗良好的單頁式網站 (SPA)、甚至是顧及 SEO 的伺服器端渲染 (SSR) 網站。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News