基于本文回答

播面 播面

刷题像听歌,多听自然懂
0
评论

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. 为什么使用并行路由?

主要有两个核心场景:

  1. 复杂的仪表盘 (Dashboards)

    • 你可以同时渲染“用户列表”和“销售图表”。
    • 独立流式传输 (Streaming):如果“销售图表”加载很慢,不会阻塞“用户列表”的显示。
    • 独立错误处理:如果“销售图表”报错,只会导致该部分显示错误 UI,而不会导致整个页面崩溃。
  2. 模态框 (Modals)

    • 结合 拦截路由 (Intercepting Routes),可以实现点击图片时 URL 改变,背景保持原页面,而图片以模态框形式浮在上面的效果(类似 Instagram 或 Pinterest)。

3. 基本用法与目录结构

假设我们要构建一个仪表盘,包含主视图、团队视图 (@team) 和分析视图 (@analytics)。

文件结构:

plaintext
app/
├── layout.js        <-- 根布局
├── page.js          <-- 对应 props.children
├── @analytics/      <-- 插槽 1
│   └── page.js
└── @team/           <-- 插槽 2
    └── page.js

代码实现 (app/layout.js):

布局组件会接收这些插槽作为 props

jsx
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。

jsx
// app/@analytics/default.js
export default function DefaultAnalytics() {
  return null; // 或者返回原本的 page 内容
}

5. 高级场景:条件渲染

你可以根据用户角色或其他逻辑来决定渲染哪个插槽。

jsx
// 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,但页面不跳转,而是弹出一个模态框显示照片。

结构:

plaintext
app/
├── feed/
│   ├── page.js
│   └── layout.js
├── @modal/              <-- 并行路由插槽
│   ├── (.)photo/[id]/   <-- 拦截路由 (拦截 /photo/id)
│   │   └── page.js      <-- 模态框内容
│   └── default.js       <-- 返回 null (默认不显示模态框)
└── photo/
    └── [id]/
        └── page.js      <-- 只有直接刷新 /photo/123 时才显示的独立页面

逻辑:

  1. app/layout.js 中引入 props.modal
  2. 当在 /feed 点击链接跳转 /photo/123 时,Next.js 拦截路由,将内容渲染在 @modal 插槽中(即模态框),背景保持 /feed 内容。
  3. 如果用户直接刷新 /photo/123,拦截失效,直接渲染 app/photo/[id]/page.js(全屏页面)。

7. 总结

Parallel Routes (并行路由) 的核心优势:

  1. 拆分布局:将单一布局拆分为多个动态部分。
  2. 独立加载:配合 loading.js,每个插槽独立显示加载骨架屏。
  3. 独立报错:配合 error.js,一个区域报错不影响其他区域。
  4. 强大的 UI 模式:是实现复杂 Dashboard 和路由级 Modal 的基石。

记住一点:如果你使用了并行路由,务必配置好 default.js,否则页面刷新时容易出现 404 错误。

00:00
00:00