動態路由
當您事先不知道確切的區段名稱,並且想要根據動態資料建立路由時,您可以使用在請求時填入的「動態區段」,或是在建置時預先渲染。
慣例
您可以將資料夾名稱用方括號括起來,以建立動態區段:`[資料夾名稱]`。例如,`[id]` 或 `[slug]`。
動態區段會以 `params` 屬性傳遞給 `layout`、`page`、`route` 和 `generateMetadata` 函式。
範例
路由 | 範例網址 | 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() 頁面,以了解如何產生區段的參數。
注意事項:動態區段相當於 `pages` 目錄中的 動態路由。
產生靜態參數 動態路由區段 結合使用,以便在建構時**靜態產生**路由,而不是在請求時按需產生。
app/blog/[slug]/page.tsxexport async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
return posts.map((post) => ({
slug: post.slug,
}))
}
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
return posts.map((post) => ({
slug: post.slug,
}))
}
`generateStaticParams` 函式的主要優點是其智慧的資料擷取方式。如果使用 `fetch` 請求在 `generateStaticParams` 函式中擷取內容,則請求會自動記憶。這表示在多個 `generateStaticParams`、佈局和頁面中使用相同參數的 `fetch` 請求只會執行一次,從而縮短建構時間。
如果您是從 `pages` 目錄遷移,請使用遷移指南。
如需更多資訊和進階使用案例,請參閱 `generateStaticParams` 伺服器函式文件。
全包區段
可以透過在括號內加入省略符號 [...folderName]
,將動態區段擴展為全包後續區段。
例如,app/shop/[...slug]/page.js
將會匹配 /shop/clothes
,也會匹配 /shop/clothes/tops
、/shop/clothes/tops/t-shirts
等等。
路由 | 範例網址 | 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/clothes
、/shop/clothes/tops
、/shop/clothes/tops/t-shirts
之外,還會匹配 /shop
。
全包和可選的全包區段之間的差異在於,使用可選的全包區段時,沒有參數的路由也會被匹配(以上述範例中的 /shop
為例)。
路由 | 範例網址 | 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 app/blog/[slug]/page.tsxexport default function Page({ params }: { params: { slug: string } }) {
return <h1>My Page</h1>
}
export default function Page({ params }: { params: { slug: string } }) {
return <h1>My Page</h1>
}