如何创建布局和页面
Next.js 使用基于文件系统的路由,这意味着你可以使用文件夹和文件来定义路由。本页将指导你如何创建布局和页面,以及它们之间的链接。
¥Next.js uses file-system based routing, meaning you can use folders and files to define routes. This page will guide you through how to create layouts and pages, and link between them.
创建页面
¥Creating a page
页面是在特定路由上渲染的 UI。要创建页面,请在 app
目录中添加 page
文件 并默认导出 React 组件。例如,要创建索引页 (/
):
¥A page is UI that is rendered on a specific route. To create a page, add a page
file inside the app
directory and default export a React component. For example, to create an index page (/
):
export default function Page() {
return <h1>Hello Next.js!</h1>
}
export default function Page() {
return <h1>Hello Next.js!</h1>
}
创建布局
¥Creating a layout
布局是多个页面之间共享的 UI。在导航时,布局会保留状态、保持交互性,并且不会重新渲染。
¥A layout is UI that is shared between multiple pages. On navigation, layouts preserve state, remain interactive, and do not rerender.
你可以通过默认从 layout
文件 导出 React 组件来定义布局。组件应接受 children
prop,可以是页面或另一个 layout。
¥You can define a layout by default exporting a React component from a layout
file. The component should accept a children
prop which can be a page or another layout.
例如,要创建一个接受索引页作为子页面的布局,请在 app
目录中添加一个 layout
文件:
¥For example, to create a layout that accepts your index page as child, add a layout
file inside the app
directory:
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
<main>{children}</main>
</body>
</html>
)
}
export default function DashboardLayout({ children }) {
return (
<html lang="en">
<body>
<main>{children}</main>
</body>
</html>
)
}
上面的布局称为 根布局,因为它是在 app
目录的根目录中定义的。根布局是必需的,并且必须包含 html
和 body
标签。
¥The layout above is called a root layout because it's defined at the root of the app
directory. The root layout is required and must contain html
and body
tags.
创建嵌套路由
¥Creating a nested route
嵌套路由是由多个 URL 段组成的路由。例如,/blog/[slug]
路由由三个段组成:
¥A nested route is a route composed of multiple URL segments. For example, the /blog/[slug]
route is composed of three segments:
-
/
(根段)¥
/
(Root Segment) -
blog
(片段)¥
blog
(Segment) -
[slug]
(叶段)¥
[slug]
(Leaf Segment)
在 Next.js 中:
¥In Next.js:
-
文件夹用于定义映射到 URL 段的路由段。
¥Folders are used to define the route segments that map to URL segments.
-
文件(如
page
和layout
)用于创建为片段显示的 UI。¥Files (like
page
andlayout
) are used to create UI that is shown for a segment.
要创建嵌套路由,你可以将文件夹嵌套在一起。例如,要为 /blog
添加路由,请在 app
目录中创建一个名为 blog
的文件夹。然后,要使 /blog
可公开访问,请添加 page
文件:
¥To create nested routes, you can nest folders inside each other. For example, to add a route for /blog
, create a folder called blog
in the app
directory. Then, to make /blog
publicly accessible, add a page
file:
import { getPosts } from '@/lib/posts'
import { Post } from '@/ui/post'
export default async function Page() {
const posts = await getPosts()
return (
<ul>
{posts.map((post) => (
<Post key={post.id} post={post} />
))}
</ul>
)
}
import { getPosts } from '@/lib/posts'
import { Post } from '@/ui/post'
export default async function Page() {
const posts = await getPosts()
return (
<ul>
{posts.map((post) => (
<Post key={post.id} post={post} />
))}
</ul>
)
}
你可以继续嵌套文件夹以创建嵌套路由。例如,要为特定博客文章创建路由,请在 blog
内创建一个新的 [slug]
文件夹并添加一个 page
文件:
¥You can continue nesting folders to create nested routes. For example, to create a route for a specific blog post, create a new [slug]
folder inside blog
and add a page
file:
function generateStaticParams() {}
export default function Page() {
return <h1>Hello, Blog Post Page!</h1>
}
function generateStaticParams() {}
export default function Page() {
return <h1>Hello, Blog Post Page!</h1>
}
很高兴知道:将文件夹名称括在方括号中(例如
[slug]
)会创建一个特殊的 动态路由段,用于从数据生成多个页面。这对于博客文章、产品页面等很有用。¥Good to know: Wrapping a folder name in square brackets (e.g.
[slug]
) creates a special dynamic route segment used to generate multiple pages from data. This is useful for blog posts, product pages, etc.
嵌套布局
¥Nesting layouts
默认情况下,文件夹层次结构中的布局也是嵌套的,这意味着它们通过其 children
属性封装子布局。你可以通过在特定路由段(文件夹)内添加 layout
来嵌套布局。
¥By default, layouts in the folder hierarchy are also nested, which means they wrap child layouts via their children
prop. You can nest layouts by adding layout
inside specific route segments (folders).
例如,要为 /blog
路由创建布局,请在 blog
文件夹内添加一个新的 layout
文件。
¥For example, to create a layout for the /blog
route, add a new layout
file inside the blog
folder.
export default function BlogLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}
export default function BlogLayout({ children }) {
return <section>{children}</section>
}
如果你要组合上述两个布局,则根布局 (app/layout.js
) 将封装博客布局 (app/blog/layout.js
),后者将封装博客 (app/blog/page.js
) 和博客文章页面 (app/blog/[slug]/page.js
)。
¥If you were to combine the two layouts above, the root layout (app/layout.js
) would wrap the blog layout (app/blog/layout.js
), which would wrap the blog (app/blog/page.js
) and blog post page (app/blog/[slug]/page.js
).
页面之间的链接
¥Linking between pages
你可以使用 <Link>
组件 在路由之间导航。<Link>
是一个内置的 Next.js 组件,它扩展了 HTML <a>
标记以提供预取和客户端导航。
¥You can use the <Link>
component to navigate between routes. <Link>
is a built-in Next.js component that extends the HTML <a>
tag to provide prefetching and client-side navigation.
例如,要生成博客文章列表,请从 next/link
导入 <Link>
并将 href
属性传递给组件:
¥For example, to generate a list of blog posts, import <Link>
from next/link
and pass a href
prop to the component:
import Link from 'next/link'
export default async function Post({ post }) {
const posts = await getPosts()
return (
<ul>
{posts.map((post) => (
<li key={post.slug}>
<Link href={`/blog/${post.slug}`}>{post.title}</Link>
</li>
))}
</ul>
)
}
import Link from 'next/link'
export default async function Post({ post }) {
const posts = await getPosts()
return (
<ul>
{posts.map((post) => (
<li key={post.slug}>
<Link href={`/blog/${post.slug}`}>{post.title}</Link>
</li>
))}
</ul>
)
}
<Link>
是在 Next.js 应用中在路由之间导航的主要和推荐方式。但是,你也可以使用 useRouter
钩 进行更高级的导航。
¥<Link>
is the primary and recommended way to navigate between routes in your Next.js application. However, you can also use the useRouter
hook for more advanced navigation.