原文链接:A Visual Guide to Layouts in Next.js 13,2023年6月15日,by Vishwas Gopinath
在上一篇文章中,我们探讨了 Next.js 中页面的概念。认识到页面代表特定路由下独一无二的用户界面。然而,在很多情况下,我们希望在应用程序中跨多个页面拥有一致的布局,例如顶部的标题和底部的页脚。随着 Next.js 版本 13 中引入布局,实现这一点变得更加容易和灵活。
Next.js 中的布局
那么,什么是布局?在 Next.js 中,布局是一个 UI 组件,在应用程序的多个页面之间共享。它允许我们为一组页面定义通用的结构和外观,减少冗余并促进代码可重用性。在 Next.js 13 中,提供了内置布局的功能支持,使创建和管理布局更加简单。
创建布局
要创建布局,我们需要创建一个名为 layout.js
或 layout.tsx
文件,定义一个 React 组件作为默认导出。布局组件会接受一个 children
prop,在渲染期间将其填充为子页面的内容。这样,子页面就成为布局的一部分,我们可以围绕它设计出表现一致的用户界面。
可视化表示
使用 create-next-app
创建 Next.js 应用时,它还会自动生成一个名为 layout.tsx
的特殊布局文件,位于 app
文件夹中。
// app/layout.tsx
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
这个文件作为最顶层的布局,通常被称为根布局(Root Layout),在每个 Next.js 应用程序中都是必需的。即使你删除了 layout.tsx
文件,Next.js 也会基于默认布局重新生成它。
让我们仔细看一下生成的 layout.tsx
文件中的代码。布局组件包含一个 children
prop,表示在布局内呈现的子页面组件。在浏览器的 HTML 结构中,有一个带有 lang="en"
属性的 <html>
标签,后面跟着<body>
标签。在 <body>
标签内部,会渲染与路由对应的页面。
以下是具有 Header
和 Footer
组件的相同布局。
// app/layout.tsx
import Header from './header'
import Footer from './footer'
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<Header />
{children}
<Footer />
</body>
</html>
);
}
页眉和页脚可以根据我们的需求进行自定义,提供所需的布局结构和样式。需要注意的是,由于布局应用于每个页面,因此无论当前路由如何,页眉和页脚都将可见。这意味着如果我们导航到不同的页面(例如 /about
或 /products
),则页眉和页脚部分始终都会渲染。
可视化表示
内嵌布局
除了根布局之外,Next.js 13 还引入了嵌套布局的概念。这个功能允许我们定义页面中某些区域的布局。
拿一个产品详情页面举例,它从路由参数动态读取产品 ID。以下是动态路由的文件夹结构:app
文件夹包含一个布局文件和 products
文件夹,products
文件夹中包含动态 [productId]
文件夹。
[productId]
文件夹中的 page.tsx
文件包含 ProductDetails
组件,这个组件将路由参数作为 prop 接收,用于在 JSX 中显示产品 ID。
// app/products/[productId]/page.tsx
export default function ProductDetails({
params,
}: {
params: { productId: string };
}) {
return <h1>Details about product {params.productId}</h1>;
}
如果我们想要为产品详情页创建一个特定布局,可以在 [productId]
文件夹内创建一个单独的布局文件 layout.tsx
。嵌套布局文件可以有自己的结构和内容,专门为增强产品详情页面的显示而设计。以下是产品详细页布局文件的代码:
// app/products/[productId]/layout.tsx
export default function ProductDetailLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<>
{children}
<h2>Featured products</h2>
{/* Carousel of featured products */}
</>
);
}
我们将嵌套布局定义为一个 React 组件,类似于根布局,也会接受一个 children
属性。这种情况下,children
prop 代表的是产品详情页的内容。作为布局的一部分,我们创建了一个特色产品的轮播图。
通过嵌套布局,我们可以创建共享 UI 组件的层次结构,仅对应用程序的特定区域使用某些布局结构。例如,根布局可以包含主要结构(如页眉和页脚),而 [productId]
件夹中的嵌套布局可以专注于显示与某个产品相关的一些产品信息。
可视化表示
总结
随着 Next.js 13 布局的引入,我们获得了巨大的灵活性和自定义选项(customization options)。我们可以在多个页面上定义表现一致的 UI 结构,减少代码重复,并轻松管理共享组件。嵌套布局更进一步扩展了这个概念,使我们能够为应用程序的不同部分创建专门的布局。