動態路由
當你事先不知道確切的區段名稱,並想從動態資料建立路由時,你可以使用動態區段,這些區段會在請求時填入,或在建置時預先渲染。
慣例
動態區段可以通過將資料夾名稱包在方括號中來建立:[folderName]
。例如,[id]
或 [slug]
。
動態區段會作為 params
屬性傳遞給 layout
、page
、route
和 generateMetadata
函式。
範例
例如,一個部落格可以包含以下路由 app/blog/[slug]/page.js
,其中 [slug]
是部落格文章的動態區段。
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>
}) {
const slug = (await params).slug
return <div>My Post: {slug}</div>
}
路由 | 範例 URL | params |
---|---|---|
app/blog/[slug]/page.js | /blog/a | { slug: 'a' } |
app/blog/[slug]/page.js | /blog/b | { slug: 'b' } |
app/blog/[slug]/page.js | /blog/c | { slug: 'c' } |
請參閱 generateStaticParams() 頁面,以了解如何為區段產生參數。
要知道
- 由於
params
屬性是一個 Promise。你必須使用 async/await 或 React 的 use 函式來存取這些值。- 在版本 14 及更早版本中,
params
是一個同步屬性。為了幫助向後相容性,你仍然可以在 Next.js 15 中同步存取它,但此行為在未來將會被棄用。
- 在版本 14 及更早版本中,
- 動態區段等同於
pages
目錄中的 動態路由。
產生靜態參數
generateStaticParams
函式可以與動態路由區段結合使用,以在建置時靜態產生路由,而不是在請求時按需產生。
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
return posts.map((post) => ({
slug: post.slug,
}))
}
generateStaticParams
函式的主要優點是其智慧型資料檢索。如果在 generateStaticParams
函式中使用 fetch
請求抓取內容,則請求會自動記憶化。這表示在多個 generateStaticParams
、版面配置和頁面中使用相同引數的 fetch
請求只會發出一次,從而縮短建置時間。
如果你是從 pages
目錄遷移,請使用遷移指南。
有關更多資訊和進階使用案例,請參閱 generateStaticParams
伺服器函式文件。
萬用字元區段
動態區段可以擴展為萬用字元後續區段,方法是在方括號內新增省略號 [...folderName]
。
例如,app/shop/[...slug]/page.js
將會匹配 /shop/clothes
,也會匹配 /shop/clothes/tops
、/shop/clothes/tops/t-shirts
等等。
路由 | 範例 URL | params |
---|---|---|
app/shop/[...slug]/page.js | /shop/a | { slug: ['a'] } |
app/shop/[...slug]/page.js | /shop/a/b | { slug: ['a', 'b'] } |
app/shop/[...slug]/page.js | /shop/a/b/c | { slug: ['a', 'b', 'c'] } |
選用性萬用字元區段
萬用字元區段可以通過將參數包含在雙方括號中來設為選用性:[[...folderName]]
。
例如,app/shop/[[...slug]]/page.js
將也會匹配 /shop
,除了 /shop/clothes
、/shop/clothes/tops
、/shop/clothes/tops/t-shirts
之外。
萬用字元區段和選用性萬用字元區段之間的區別在於,對於選用性萬用字元區段,不帶參數的路由也會被匹配(在上面的範例中為 /shop
)。
路由 | 範例 URL | params |
---|---|---|
app/shop/[[...slug]]/page.js | /shop | { slug: undefined } |
app/shop/[[...slug]]/page.js | /shop/a | { slug: ['a'] } |
app/shop/[[...slug]]/page.js | /shop/a/b | { slug: ['a', 'b'] } |
app/shop/[[...slug]]/page.js | /shop/a/b/c | { slug: ['a', 'b', 'c'] } |
TypeScript
當使用 TypeScript 時,你可以根據你設定的路由區段為 params
新增類型。
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>
}) {
return <h1>My Page</h1>
}
路由 | params 類型定義 |
---|---|
app/blog/[slug]/page.js | { slug: string } |
app/shop/[...slug]/page.js | { slug: string[] } |
app/shop/[[...slug]]/page.js | { slug?: string[] } |
app/[categoryId]/[itemId]/page.js | { categoryId: string, itemId: string } |
要知道:這可能會在未來由 TypeScript 外掛程式 自動完成。
下一步
這有幫助嗎?