Dynamic Routes 动态路由
When you don't know the exact segment names ahead of time and want to create routes from dynamic data, you can use Dynamic Segments that are filled in at request time or prerendered at build time.
如果您事先不知道确切的段名称,并且希望从动态数据创建路由,则可以使用在请求时填充或在构建时预先呈现的动态段。
1.Convention 约定
A Dynamic Segment can be created by wrapping a folder's name in square brackets: [folderName]. For example, [id] or [slug].
可以通过用方括号括起文件夹的名称来创建动态段: [folderName] 。例如, [id] 或 [slug] 。
Dynamic Segments are passed as the params prop to layout, page, route, and generateMetadata functions.
动态段作为 params 属性传递给 layout 、 page 、 route 和 generateMetadata 函数。
2.Example 示例
For example, a blog could include the following route app/blog/[slug]/page.js where [slug] is the Dynamic Segment for blog posts.
例如,博客可以包含以下路由 app/blog/[slug]/page.js ,其中 [slug] 是博客文章的动态段。
// app/blog/[slug]/page.tsx
export default function Page({ params }: { params: { slug: string } }) {
return <div>My Post: {params.slug}</div>
}
Route | Example URL |
|
---|---|---|
|
|
|
|
|
|
|
|
|
See the generateStaticParams() page to learn how to generate the params for the segment.
请参阅 generateStaticParams() 页面,了解如何为该段生成参数。
Good to know: Dynamic Segments are equivalent to Dynamic Routes in the pages directory.
值得注意的是:动态段等同于 pages 目录中的动态路由。
3.Generating Static Params 生成静态参数
The generateStaticParams function can be used in combination with dynamic route segments to statically generate routes at build time instead of on-demand at request time.
可以使用 generateStaticParams 函数结合动态路由段在构建时静态生成路由,而不是在请求时按需生成路由。
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
return posts.map((post) => ({
slug: post.slug,
}))
}
The primary benefit of the generateStaticParams function is its smart retrieval of data. If content is fetched within the generateStaticParams function using a fetch request, the requests are automatically memoized. This means a fetch request with the same arguments across multiple generateStaticParams, Layouts, and Pages will only be made once, which decreases build times.
generateStaticParams 函数的主要好处是其智能检索数据。如果在 generateStaticParams 函数中使用 fetch 请求获取内容,则请求会自动记忆。这意味着在多个 generateStaticParams 、布局和页面中具有相同参数的 fetch 请求只会进行一次,从而减少构建时间。
4.Catch-all Segments 万能段
Dynamic Segments can be extended to catch-all subsequent segments by adding an ellipsis inside the brackets [...folderName].
动态段可以通过在括号 [...folderName] 内添加省略号来扩展以捕获所有后续段。
For example, app/shop/[...slug]/page.js will match /shop/clothes, but also /shop/clothes/tops, /shop/clothes/tops/t-shirts, and so on.
例如, app/shop/[...slug]/page.js 将匹配 /shop/clothes ,还将匹配 /shop/clothes/tops 、 /shop/clothes/tops/t-shirts 等。
Route | Example URL |
|
---|---|---|
|
|
|
|
|
|
|
|
|
5.Optional Catch-all Segments 可选的捕获所有段
Catch-all Segments can be made optional by including the parameter in double square brackets: [[...folderName]].
可以通过将参数包含在双中括号中来使捕获所有段变为可选: [[...folderName]] 。
For example, app/shop/[[...slug]]/page.js will also match /shop, in addition to /shop/clothes, /shop/clothes/tops, /shop/clothes/tops/t-shirts.
例如, app/shop/[[...slug]]/page.js 除了匹配 /shop/clothes 、 /shop/clothes/tops 、 /shop/clothes/tops/t-shirts 之外,还将匹配 /shop 。
The difference between catch-all and optional catch-all segments is that with optional, the route without the parameter is also matched (/shop in the example above).
catch-all 段和可选 catch-all 段之间的区别在于,对于可选段,不带参数的路由也会匹配(在上面的示例中为 /shop )。
Route | Example URL |
|
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
6.TypeScript
When using TypeScript, you can add types for params depending on your configured route segment.
使用 TypeScript 时,您可以根据配置的路由段为 params 添加类型。
export default function Page({ params }: { params: { slug: string } }) {
return <h1>My Page</h1>
}
Route |
|
---|---|
|
|
|
|
|
|
|
|
Good to know: This may be done automatically by the TypeScript plugin in the future.
温馨提示:将来 TypeScript 插件可能会自动完成此操作。