跳转到内容

Next.js平行路由

来自代码酷

模板:Note

Next.js平行路由[编辑 | 编辑源代码]

平行路由(Parallel Routes)是Next.js 13+引入的高级路由模式,允许在同一布局中同时条件性渲染多个独立的路由段。这种模式打破了传统线性路由的层级限制,特别适合构建复杂界面如仪表盘、多视图应用等场景。

核心概念[编辑 | 编辑源代码]

平行路由的核心特征包括:

  • 独立加载:每个路由段拥有独立的加载状态和错误边界
  • 共享URL:所有平行路由段共享相同的URL路径
  • 动态组合:可通过条件逻辑控制不同路由段的显示

与传统嵌套路由对比[编辑 | 编辑源代码]

graph LR A[传统嵌套路由] --> B[父布局] B --> C[子页面] C --> D[孙子页面] E[平行路由] --> F[布局] F --> G[路由段A] F --> H[路由段B] F --> I[路由段C]

实现机制[编辑 | 编辑源代码]

平行路由通过特殊的命名插槽实现。在Next.js文件系统中,使用@folder约定定义平行路由段:

app/
├── @sidebar/
│   └── page.tsx
├── @content/
│   └── page.tsx
└── layout.tsx

基础示例[编辑 | 编辑源代码]

以下是一个仪表盘布局的平行路由实现:

// app/dashboard/layout.tsx
export default function Layout({
  children,
  sidebar,
  content
}: {
  children: React.ReactNode
  sidebar: React.ReactNode
  content: React.ReactNode
}) {
  return (
    <div className="dashboard">
      <nav className="sidebar">{sidebar}</nav>
      <main className="content">{content}</main>
      <aside className="widgets">{children}</aside>
    </div>
  )
}

高级用法[编辑 | 编辑源代码]

条件渲染[编辑 | 编辑源代码]

平行路由可以与React的条件渲染结合:

// app/dashboard/layout.tsx
export default function Layout({
  sidebar,
  content
}: {
  sidebar: React.ReactNode
  content: React.ReactNode
}) {
  const [viewMode] = useViewMode() // 'full' | 'compact'
  
  return (
    <>
      {viewMode === 'full' && sidebar}
      {content}
    </>
  )
}

动态插槽[编辑 | 编辑源代码]

通过插槽名称的动态计算实现更灵活的配置:

// app/[tab]/layout.tsx
export default function Layout({
  params,
  analytics,
  settings
}: {
  params: { tab: string }
  analytics: React.ReactNode
  settings: React.ReactNode
}) {
  const CurrentTab = params.tab === 'analytics' ? analytics : settings
  
  return <div>{CurrentTab}</div>
}

实际案例[编辑 | 编辑源代码]

案例1:可折叠侧边栏[编辑 | 编辑源代码]

实现一个保留状态的可折叠侧边栏:

stateDiagram-v2 [*] --> Expanded Expanded --> Collapsed: 点击折叠按钮 Collapsed --> Expanded: 点击展开按钮

对应代码实现:

// app/layout.tsx
'use client'

export default function Layout({
  sidebar,
  content
}: {
  sidebar: React.ReactNode
  content: React.ReactNode
}) {
  const [isExpanded, setIsExpanded] = useState(true)
  
  return (
    <div className={`container ${isExpanded ? 'expanded' : 'collapsed'}`}>
      <div className="sidebar-wrapper">
        <button onClick={() => setIsExpanded(!isExpanded)}>
          {isExpanded ? '◀' : '▶'}
        </button>
        {isExpanded && sidebar}
      </div>
      {content}
    </div>
  )
}

案例2:多步骤表单[编辑 | 编辑源代码]

使用平行路由实现表单步骤的持久化状态:

app/
├── @step1/
│   └── page.tsx
├── @step2/
│   └── page.tsx
├── @step3/
│   └── page.tsx
└── layout.tsx
// app/layout.tsx
export default function FormWizard({
  step1,
  step2,
  step3,
  params
}: {
  step1: React.ReactNode
  step2: React.ReactNode
  step3: React.ReactNode
  params: { step: string }
}) {
  return (
    <form>
      {params.step === '1' && step1}
      {params.step === '2' && step2}
      {params.step === '3' && step3}
    </form>
  )
}

性能考量[编辑 | 编辑源代码]

平行路由通过路由段隔离带来多项性能优势:

  • 更细粒度的加载:每个路由段有独立的loading.tsx
  • 局部更新:仅重新渲染变更的路由段
  • 预加载控制:可通过prefetch单独控制

数学表达并行加载效益: Tparallel=max(T1,T2,...,Tn) Tsequential=i=1nTi

其中Tn表示第n个路由段的加载时间。

常见问题[编辑 | 编辑源代码]

页面模块:Message box/ambox.css没有内容。

  • TypeScript类型:需要手动定义插槽props类型
  • 默认路由:未匹配时会渲染default.js或空白
  • 服务器组件:平行路由段默认是服务器组件

最佳实践[编辑 | 编辑源代码]

1. 命名一致性:保持插槽名称与目录名一致 2. 错误隔离:为每个路由段添加error.tsx 3. 加载状态:设计有意义的加载指示器 4. URL设计:合理规划路由参数

模板:Tip

进阶阅读[编辑 | 编辑源代码]

  • Next.js官方文档:Parallel Routes RFC
  • React模式:Composition vs Inheritance
  • 前端架构:Micro Frontends设计模式