昨天,我們已經學習了如何建立文章列表頁面。
今天,我們將進一步學習如何在 Astro 專案中實現分頁功能,以便更好地管理和顯示內容,特別是當內容列表變得過長時。我們將使用 Tailwind Components 這個分頁樣版來套用。
在前幾篇文章中,我們已經了解了如何設置 Astro 的路由。分頁功能實際上就是通過路由來實現的。首先,我們需要在 src/blog/pages
目錄中建立一個 [page].astro
文件,這個文件將處理分頁的顯示和內容。
程式碼如下:
---
import { getCollection } from 'astro:content';
import MainLayout from '../../../layouts/MainLayout.astro';
import { SITE_TITLE, SITE_DESCRIPTION } from '../../../consts';
import { sortByDate } from '../../../lib/sortByDate';
import FormattedDate from '../../../components/FormattedDate.astro';
import type { GetStaticPathsOptions, Page, } from 'astro';
export async function getStaticPaths(options: GetStaticPathsOptions) {
const { paginate } = options;
const posts = sortByDate(await getCollection('blog'))
return paginate(posts, { pageSize: 2 });
}
interface Props {
page: Page;
}
const { page } = Astro.props;
const { data, url, start, end, total, size, currentPage, lastPage } = page;
const { prev, next, current } = url;
---
<MainLayout title={SITE_TITLE} description={SITE_DESCRIPTION}>
<main>
<section>
<ul>
{
data.map((post) => (
<p>
<FormattedDate date={post.data.pubDate} />{' '}
<a href={`/blog/${post.slug}/`}>{post.data.title}</a>
</p>
))
}
</ul>
</section>
<div class="flex flex-col items-center my-12">
<div class="flex text-gray-700">
{
!!prev && (
<a
href={prev}
class="h-12 w-12 mr-1 flex justify-center items-center rounded-full"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="100%"
height="100%"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="feather feather-chevron-left w-6 h-6"
>
<polyline points="15 18 9 12 15 6" />
</svg>
</a>
)
}
{
[...Array(lastPage).keys()].map((e: number) => {
return (
<a href={`/blog/page/${e + 1}/`}
class={`w-12 flex justify-center items-center cursor-pointer leading-5 transition duration-150 ease-in rounded-full ${
currentPage === e + 1
? 'bg-teal-600 text-white'
: 'text-default'
}`}
>
{e + 1}
</a>
)
})
}
{
!!next && (
<a
href={next}
class="h-12 w-12 ml-1 flex justify-center items-center rounded-full cursor-pointer"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="100%"
height="100%"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="feather feather-chevron-right w-6 h-6"
>
<polyline points="9 18 15 12 9 6" />
</svg>
</a>
)
}
</div>
</div>
</main>
</MainLayout>
export async function getStaticPaths(options: GetStaticPathsOptions) {
const { paginate } = options;
const posts = sortByDate(await getCollection("blog"));
return paginate(posts, { pageSize: 2 });
}
在這一部分,我們使用 getStaticPaths
函數來設定分頁路徑。我們首先取得部落格文章集合,然後使用 paginate
函數將文章按照每頁 2 篇
的方式分割成多個分頁。這將生成不同的路徑,例如 /blog/page/1/
、/blog/page/2/
等。
const { page } = Astro.props;
const { data, url, start, end, total, size, currentPage, lastPage } = page;
const { prev, next, current } = url;
變數的設定如下:
<MainLayout title={SITE_TITLE} description={SITE_DESCRIPTION}>
<main>
<section>
<ul>
{
data.map((post) => (
<p>
<FormattedDate date={post.data.pubDate} />{' '}
<a href={`/blog/${post.slug}/`}>{post.data.title}</a>
</p>
))
}
</ul>
</section>
<div class="flex flex-col items-center my-12">
<div class="flex text-gray-700">
{
!!prev && (
<a
href={prev}
class="h-12 w-12 mr-1 flex justify-center items-center rounded-full"
>
<!-- 上一頁圖示 -->
</a>
)
}
{
[...Array(lastPage).keys()].map((e: number) => {
return (
<a href={`/blog/page/${e + 1}/`}
class={`w-12 flex justify-center items-center cursor-pointer leading-5 transition duration-150 ease-in rounded-full ${
currentPage === e + 1
? 'bg-teal-600 text-white'
: 'text-default'
}`}
>
{e + 1}
</a>
)
})
}
{
!!next && (
<a
href={next}
class="h-12 w-12 ml-1 flex justify-center items-center rounded-full cursor-pointer"
>
<!-- 下一頁圖示 -->
</a>
)
}
</div>
</div>
</main>
</MainLayout>
最後,我們在 MainLayout
中顯示分頁內容。遍歷 data
陣列,顯示每篇文章的標題和發布日期。在分頁控制部分,根據上一頁
和下一頁
的路徑來顯示相應的分頁連結。
今天,我們學到了:
範例連結:https://stackblitz.com/edit/withastro-astro-kclbjr
https://docs.astro.build/en/reference/api-reference/#paginate
https://docs.astro.build/en/core-concepts/routing/#pagination