分頁(pagination)就是把一些資料每幾筆資料分成一組放在同一頁,產生若干頁的頁面。比方說現在有 100 筆資料,每頁放 7 筆資料,經過分頁就會產生 15 個頁面,在最後的第 15 頁只會有最後的 2 筆資料。
Astro 的 paginate()
函式
Astro 有內建 paginate()
函式可以做到分頁功能。下面就用稍微修改過的官方文件的例子來說明這個函式:
這個檔案會將 astronauts
陣列做分頁,產生的頁面會在 /astronauts
(第一頁)、/astronauts/2
、/astronauts/3
…以此類推。(如果是原版官方文件的例子,第一頁會在 /astronauts/1
,差別在於檔名不同。)
paginate()
函式不需要另外引入,只要在 getStaticPaths()
做為參數引入就可以使用。如果在這個函式裡回傳 paginate()
的回傳值,產生的頁面會有 page
prop 可以使用。這個 prop 除了分頁後的資料 page.data
外,還有像上/下一頁的連結(page.url.prev
/ page.url.next
)之類有用的屬性。
paginate()
的不足與暫時解法
不過我覺得這樣的 url 可能造成誤解。拿上面的例子來說,/astronauts/2
可能被誤解成二號太空人,而不是太空人清單的第二頁。如果把這個檔案移到 src/pages/astronauts/page/[...page].astro
,雖然第二頁 /astronauts/page/2
就不會造成誤解了,但是第一頁的 /astronauts/page
又會覺得很奇怪,我會想要它在原來的 /astronauts
。
要達成這個目標,除了自己寫分頁的邏輯以外,也可以在有用 paginate()
的程式碼做一些更改。想法大致上是把第一頁跟其他頁分開,第一頁自己做分頁,不使用 paginate()
,其他頁照樣使用 paginate()
,但是要把 paginate()
產生的第一頁去掉,還要把第二頁往上一頁的連結替換成我們自己寫的第一頁連結。
第一頁在 src/pages/astronauts/index.astro
,不使用 dynamic routing,所以也不會有 getStaticPaths()
。在這一頁自己拿這一頁會有的資料做 render,另外自己設定往第二頁的連結(如果有第二頁的話)。
其他頁在 src/pages/astronauts/page/[...page].astro
,一樣有 paginate()
,但是要把第一頁去掉,所以要改成:
然後還要判斷如果是在第二頁的話,不能用 page
prop 的 page.url.prev
,必須自己設定往第一頁的連結。
沒被採納的提議
在 Astro roadmap 有人提出讓 paginate()
可以首頁跟其他頁路徑分開的建議(這個跟這個),可惜除了我以外似乎沒有人理的樣子,更不用說進入後續階段了。現在如果想要這樣做的話,除了自己寫外,就只能做上述的 workaround 了。