文章目录
Next.js 是一个流行的 React 全栈框架,它的文件系统路由机制提供了直观、高效的方式来定义和管理应用的路由。本文将详细介绍 Next.js 的文件系统路由机制,包括静态路由、动态路由和相关实践,帮助你充分理解这一强大特性。
一、文件系统路由机制概述
1. 什么是文件系统路由?
Next.js 的文件系统路由机制是基于文件夹和文件结构的路由方式。换句话说,app
或 pages
目录中的文件和文件夹会自动映射到应用的 URL 路径,无需额外的路由配置。
文件系统映射规则:
- 页面文件:每个
.tsx
或.js
文件都会映射为一个页面路由。 - 文件夹:文件夹层级会被映射为 URL 路径的分层。
例如:
app/
page.tsx -> '/'
about.tsx -> '/about'
blog/
page.tsx -> '/blog'
[id].tsx -> '/blog/[id]' (动态路由)
这种直观的文件夹结构大大降低了管理复杂路由的成本。
2. 为什么选择文件系统路由?
文件系统路由的优势:
- 零配置:不需要单独编写路由文件。
- 直观性:路由结构与文件结构保持一致,易于维护。
- 强大扩展性:支持动态路由、嵌套路由和 API 路由。
二、静态路由的基本用法
1. 静态路由示例
创建以下 app
文件结构:
app/
page.tsx
about.tsx
contact.tsx
代码示例:
// app/page.tsx
export default function Home() {
return <h1>欢迎来到首页</h1>;
}
// app/about.tsx
export default function About() {
return <h1>关于我们</h1>;
}
// app/contact.tsx
export default function Contact() {
return <h1>联系我们</h1>;
}
生成的路由为:
/
->app/page.tsx
/about
->app/about.tsx
/contact
->app/contact.tsx
2. 如何在页面之间导航?
Next.js 提供了 Link
组件用于路由跳转:
import Link from 'next/link';
export default function Home() {
return (
<nav>
<Link href="/about">关于我们</Link>
<Link href="/contact">联系我们</Link>
</nav>
);
}
三、动态路由详解
1. 动态路由的概念
动态路由允许在 URL 中使用动态参数。Next.js 使用方括号 [ ]
来定义动态路由。
示例:
app/
blog/
[id].tsx -> '/blog/[id]'
动态路由代码:
// app/blog/[id].tsx
import { useRouter } from 'next/router';
export default function BlogPost() {
const router = useRouter();
const { id } = router.query;
return <h1>博客文章 ID: {id}</h1>;
}
2. 如何生成动态链接?
在动态路由页面中,我们可以通过 <Link>
生成动态链接:
import Link from 'next/link';
const BlogList = () => {
const posts = [
{ id: 1, title: '文章一' },
{ id: 2, title: '文章二' },
];
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link href={`/blog/${post.id}`}>{post.title}</Link>
</li>
))}
</ul>
);
};
export default BlogList;
点击生成的链接,例如 /blog/1
,会自动映射到 app/blog/[id].tsx
。
四、嵌套路由与布局
1. 嵌套路由的概念
嵌套路由允许我们根据文件夹层级创建更复杂的路由结构。
示例:
app/
dashboard/
page.tsx -> '/dashboard'
settings.tsx -> '/dashboard/settings'
users/
[id].tsx -> '/dashboard/users/[id]'
2. 嵌套路由代码示例
文件结构:
app/
dashboard/
page.tsx
settings.tsx
users/
[id].tsx
代码:
// app/dashboard/page.tsx
export default function Dashboard() {
return <h1>仪表盘首页</h1>;
}
// app/dashboard/settings.tsx
export default function Settings() {
return <h1>设置页面</h1>;
}
// app/dashboard/users/[id].tsx
import { useRouter } from 'next/router';
export default function User() {
const { id } = useRouter().query;
return <h1>用户详情 ID: {id}</h1>;
}
五、动态参数与 getStaticProps/getServerSideProps
在动态路由中,Next.js 支持使用 getStaticProps
或 getServerSideProps
获取动态参数并生成页面。
示例:静态生成
// app/blog/[id].tsx
export async function getStaticPaths() {
return {
paths: [
{ params: { id: '1' } },
{ params: { id: '2' } },
],
fallback: false,
};
}
export async function getStaticProps({ params }: { params: { id: string } }) {
return {
props: {
id: params.id,
},
};
}
export default function BlogPost({ id }: { id: string }) {
return <h1>博客文章 ID: {id}</h1>;
}
示例:服务端渲染
// app/blog/[id].tsx
export async function getServerSideProps({ params }: { params: { id: string } }) {
return {
props: {
id: params.id,
},
};
}
export default function BlogPost({ id }: { id: string }) {
return <h1>博客文章 ID: {id}</h1>;
}
六、路由的进阶特性
1. 捕获所有路由
通过 [...slug].tsx
创建捕获所有路由的页面:
// app/blog/[...slug].tsx
import { useRouter } from 'next/router';
export default function Blog() {
const router = useRouter();
const { slug } = router.query;
return <h1>Slug: {JSON.stringify(slug)}</h1>;
}
2. 自定义 404 页面
通过创建 app/404.tsx
定义自定义的 404 页面:
export default function Custom404() {
return <h1>页面未找到</h1>;
}
推荐: