Astro - 基礎入門2.第二課練習題實作

更新 發佈閱讀 7 分鐘

題目

任務目標: 實作「動態路由」,讓點擊列表後能看到文章內容。
這在 Astro 中是非常經典的步驟,請嘗試完成以下開發:

  1. 建立檔案 src/pages/posts/[id].astro。(注意檔名有中括號,代表這是動態路徑)。
  2. 使用 getStaticPaths() 函式來告訴 Astro 你有哪些文章要生成頁面。
  3. 使用 render(post) 函式(從 astro:content 匯入)來渲染 Markdown 內容。

參考提示代碼:

---
import { getCollection, render } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';

export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(post => ({
params: { id: post.id },
props: { post },
}));
}

const { post } = Astro.props;
const { Content } = await render(post);
---
<BaseLayout pageTitle={post.data.title}>
<Content />
</BaseLayout>

挑戰題: 在 src/pages/blog.astro 頁面中,試著讓列表按日期排序,最新的文章排在最前面。(提示:使用 JavaScript 的 sort() 方法操作 allPosts)。

目前專案結構

📁 .astro/
📁 .vscode/
📁 node_modules/
📁 public/
└─ favicon.svg
📁 src/
├─ 📁 content/
│ ├─ 📁 blog/
│ │ └─ post-1.md
│ └─ config.ts
├─ 📁 layouts/
│ └─ BaseLayout.astro
└─ 📁 pages/
├─ about.astro
├─ blog.astro
└─ index.astro
.gitignore
astro.config.mjs
package-lock.json
package.json
README.md
tsconfig.json

1_新增 src/pages/posts/[id].astro

---
import { getCollection, render } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';

export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(post => ({
params: { id: post.id },
props: { post },
}));
}

const { post } = Astro.props;
const { Content } = await render(post);
---

<BaseLayout pageTitle={post.data.title}>
<Content />
</BaseLayout>

2_挑戰題

2_1. 修改 src/pages/blog.astro

---
import { getCollection } from 'astro:content'
import type { CollectionEntry } from 'astro:content'
import BaseLayout from '../layouts/BaseLayout.astro'

const pageTitle = '我的部落格'
const allPosts: CollectionEntry<'blog'>[] = await getCollection('blog')
---

<BaseLayout pageTitle={pageTitle}>
  <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會員
26內容數
李昀瑾的沙龍的其他內容
2026/01/09
Astro 5.1.x 的重點在於如何管理內容 以前我們可能要手動 fs.readFileSync,現在我們用 Content Layer API,它能讓你的 Markdown 檔案擁有強大的型別檢查 (Type Safety)。 第二課:Content Collections (內容集) ——
Thumbnail
2026/01/09
Astro 5.1.x 的重點在於如何管理內容 以前我們可能要手動 fs.readFileSync,現在我們用 Content Layer API,它能讓你的 Markdown 檔案擁有強大的型別檢查 (Type Safety)。 第二課:Content Collections (內容集) ——
Thumbnail
2026/01/08
Astro - 基礎入門1.第一課練習題實作
2026/01/08
Astro - 基礎入門1.第一課練習題實作
2026/01/08
第一課:Astro 的靈魂 —— 組件與佈局 (Layouts) 在 Astro 中,網頁是由一個個 .astro 檔案組成的。這類檔案最大的特色是:預設不發送任何 JavaScript 到瀏覽器,所以速度極快。
2026/01/08
第一課:Astro 的靈魂 —— 組件與佈局 (Layouts) 在 Astro 中,網頁是由一個個 .astro 檔案組成的。這類檔案最大的特色是:預設不發送任何 JavaScript 到瀏覽器,所以速度極快。
看更多