題目
任務目標: 實作「動態路由」,讓點擊列表後能看到文章內容。
這在 Astro 中是非常經典的步驟,請嘗試完成以下開發:
- 建立檔案
src/pages/posts/[id].astro。(注意檔名有中括號,代表這是動態路徑)。 - 使用
getStaticPaths()函式來告訴 Astro 你有哪些文章要生成頁面。 - 使用
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>
