Next.js的Parallel Routes(并行路由)
Next.js 的 Parallel Routes(并行路由) 是 App Router 架构中一个非常强大的功能,它允许你在同一个布局(Layout)中同时或者有条件地渲染一个或多个页面。
简单来说,它就像是前端框架(如 Vue)中的“具名插槽”(Named Slots),允许你将页面分割成不同的独立部分,每一部分都有自己的路由逻辑、加载状态和错误处理。
以下是关于 Parallel Routes 的详细指南:
1. 核心概念:插槽 (Slots)
并行路由通过 “插槽” 来实现。
- 命名规则:使用
@符号作为文件夹的前缀(例如@analytics)。 - 特性:以
@开头的文件夹不会影响 URL 路径。例如,app/@analytics/page.js的路由依然是/,而不是/analytics。
2. 为什么使用并行路由?
主要有两个核心场景:
复杂的仪表盘 (Dashboards):
- 你可以同时渲染“用户列表”和“销售图表”。
- 独立流式传输 (Streaming):如果“销售图表”加载很慢,不会阻塞“用户列表”的显示。
- 独立错误处理:如果“销售图表”报错,只会导致该部分显示错误 UI,而不会导致整个页面崩溃。
模态框 (Modals):
- 结合 拦截路由 (Intercepting Routes),可以实现点击图片时 URL 改变,背景保持原页面,而图片以模态框形式浮在上面的效果(类似 Instagram 或 Pinterest)。
3. 基本用法与目录结构
假设我们要构建一个仪表盘,包含主视图、团队视图 (@team) 和分析视图 (@analytics)。
文件结构:
app/
├── layout.js <-- 根布局
├── page.js <-- 对应 props.children
├── @analytics/ <-- 插槽 1
│ └── page.js
└── @team/ <-- 插槽 2
└── page.js
代码实现 (app/layout.js):
布局组件会接收这些插槽作为 props。
export default function Layout({ children, team, analytics }) {
return (
<html>
<body>
<h1>我的仪表盘</h1>
{/* 主页面内容 (app/page.js) */}
<div>{children}</div>
<div className="dashboard-grid">
{/* 渲染 @team 插槽 */}
<div className="column">
{team}
</div>
{/* 渲染 @analytics 插槽 */}
<div className="column">
{analytics}
</div>
</div>
</body>
</html>
)
}
4. 关键文件:default.js (非常重要)
这是初学者最容易遇到的坑。
当用户在应用内导航(软导航)时,Next.js 会保留插槽的当前状态。但是,当用户刷新页面(硬导航)或直接访问某个 URL 时,Next.js 需要知道每个插槽应该渲染什么。
如果当前的 URL 不能匹配某个插槽中的路由,Next.js 会尝试查找该插槽下的 default.js 文件。
- 如果有
default.js:渲染该文件内容。 - 如果没有
default.js:Next.js 会渲染 404 页面。
最佳实践:为你的每个并行路由插槽都创建一个 default.js。通常它的内容和该插槽的 page.js 一样,或者是一个空的 fallback。
// app/@analytics/default.js
export default function DefaultAnalytics() {
return null; // 或者返回原本的 page 内容
}
5. 高级场景:条件渲染
你可以根据用户角色或其他逻辑来决定渲染哪个插槽。
// app/layout.js
import { getUserRole } from '@/lib/auth';
export default function Layout({ children, admin, user }) {
const role = getUserRole();
return (
<>
{children}
{/* 根据角色渲染不同的插槽 */}
{role === 'admin' ? admin : user}
</>
);
}
6. 结合拦截路由实现 Modals (模态框)
这是并行路由最酷的用法。场景:用户在 /feed 页面,点击一张照片,URL 变为 /photo/123,但页面不跳转,而是弹出一个模态框显示照片。
结构:
app/
├── feed/
│ ├── page.js
│ └── layout.js
├── @modal/ <-- 并行路由插槽
│ ├── (.)photo/[id]/ <-- 拦截路由 (拦截 /photo/id)
│ │ └── page.js <-- 模态框内容
│ └── default.js <-- 返回 null (默认不显示模态框)
└── photo/
└── [id]/
└── page.js <-- 只有直接刷新 /photo/123 时才显示的独立页面
逻辑:
- 在
app/layout.js中引入props.modal。 - 当在
/feed点击链接跳转/photo/123时,Next.js 拦截路由,将内容渲染在@modal插槽中(即模态框),背景保持/feed内容。 - 如果用户直接刷新
/photo/123,拦截失效,直接渲染app/photo/[id]/page.js(全屏页面)。
7. 总结
Parallel Routes (并行路由) 的核心优势:
- 拆分布局:将单一布局拆分为多个动态部分。
- 独立加载:配合
loading.js,每个插槽独立显示加载骨架屏。 - 独立报错:配合
error.js,一个区域报错不影响其他区域。 - 强大的 UI 模式:是实现复杂 Dashboard 和路由级 Modal 的基石。
记住一点:如果你使用了并行路由,务必配置好 default.js,否则页面刷新时容易出现 404 错误。