Next.js 平行路由:构建模块化动态布局

文章目录

在现代 Web 应用开发中,我们经常需要构建复杂的界面布局,比如仪表盘、社交平台或管理后台。传统的路由方式往往无法满足这种动态、多部分同时更新的需求。这就是 Next.js 平行路由大显身手的地方。

什么是平行路由?

平行路由(Parallel Routes)是 Next.js 的一个高级特性,它允许你在同一个布局中同时渲染多个页面,每个页面都可以独立管理和更新。

核心概念速览

概念 说明 示例
插槽 (@folder) 定义平行路由的特殊文件夹 @analytics, @sidebar
布局集成 插槽作为 props 传递给布局 { children, analytics, sidebar }
条件渲染 基于状态动态显示不同插槽 {isAdmin ? admin : user}
独立状态管理 每个插槽有自己的加载和错误状态 @team/loading.js

快速上手:构建仪表盘布局

让我们通过一个实际的仪表盘案例来探索平行路由的强大功能。

项目结构

复制代码
app/
├── dashboard/
│   ├── @analytics/
│   │   ├── page.js
│   │   └── loading.js
│   ├── @sidebar/
│   │   ├── page.js
│   │   └── default.js
│   ├── layout.js
│   ├── page.js
│   └── default.js

1. 定义插槽布局

js 复制代码
// app/dashboard/layout.js
export default function DashboardLayout({ children, analytics, sidebar }) {
  return (
    <div className="dashboard-container">
      {/* 主导航区域 */}
      <nav className="main-nav">
        <h1>企业仪表盘</h1>
      </nav>

      <div className="dashboard-content">
        {/* 侧边栏插槽 */}
        <aside className="sidebar">{sidebar}</aside>

        {/* 主内容区域 */}
        <main className="main-content">{children}</main>

        {/* 分析面板插槽 */}
        <section className="analytics-panel">{analytics}</section>
      </div>
    </div>
  );
}

2. 创建各个插槽内容

主内容区域:

js 复制代码
// app/dashboard/page.js
export default function DashboardPage() {
  return (
    <div>
      <h2>欢迎回来!</h2>
      <p>今日概览和重要通知...</p>
    </div>
  );
}

分析面板插槽:

js 复制代码
// app/dashboard/@analytics/page.js
export default function AnalyticsPanel() {
  return (
    <div className="analytics-card">
      <h3>实时数据</h3>
      <div className="metrics">
        <div className="metric">访问量: 1,234</div>
        <div className="metric">转化率: 68%</div>
      </div>
    </div>
  );
}

// 独立的加载状态
export function AnalyticsLoading() {
  return <div className="analytics-card loading">分析数据加载中...</div>;
}

侧边栏插槽:

js 复制代码
// app/dashboard/@sidebar/page.js
export default function Sidebar() {
  return (
    <nav className="sidebar-nav">
      <ul>
        <li>
          <a href="/dashboard">首页</a>
        </li>
        <li>
          <a href="/dashboard/analytics">分析</a>
        </li>
        <li>
          <a href="/dashboard/settings">设置</a>
        </li>
      </ul>
    </nav>
  );
}

高级特性深度探索

1. 条件渲染:基于用户角色的动态布局

js 复制代码
// app/dashboard/layout.js
export default function DashboardLayout({ children, admin, user, analytics }) {
  const userRole = getUserRole(); // 你的权限逻辑

  return (
    <div className="dashboard-container">
      <nav className="main-nav">...</nav>

      <div className="dashboard-content">
        <aside className="sidebar">
          {/* 根据角色显示不同侧边栏 */}
          {userRole === "admin" ? admin : user}
        </aside>

        <main className="main-content">{children}</main>

        <section className="analytics-panel">{analytics}</section>
      </div>
    </div>
  );
}

2. 结合拦截路由实现模态框

平行路由与拦截路由的结合可以创建出色的用户体验:

复制代码
app/
├── @modal/
│   └── (.)photo/
│       └── [id]/
│           └── page.js
├── photo/
│   └── [id]/
│       └── page.js
└── layout.js
js 复制代码
// app/layout.js
export default function Layout({ children, modal }) {
  return (
    <html>
      <body>
        {children}
        {modal}
      </body>
    </html>
  );
}

// app/@modal/(.)photo/[id]/page.js
export default function PhotoModal({ params }) {
  return (
    <div className="modal-overlay">
      <div className="modal-content">
        <img src={`/photos/${params.id}`} alt="Preview" />
        <a href="/">关闭</a>
      </div>
    </div>
  );
}

3. 错误边界和加载状态

每个插槽都可以有自己的错误处理和加载状态:

js 复制代码
// app/dashboard/@analytics/error.js
'use client';

export default function AnalyticsError({ error, reset }) {
  return (
    <div className="analytics-error">
      <h3>数据分析加载失败</h3>
      <button onClick={reset}>重试</button>
    </div>
  );
}

// app/dashboard/@analytics/loading.js
export default function AnalyticsLoading() {
  return (
    <div className="analytics-loading">
      <div className="loading-spinner"></div>
      <p>数据加载中...</p>
    </div>
  );
}

解决常见问题

1. 硬导航后的默认内容

js 复制代码
// app/dashboard/default.js
export default function DefaultDashboard() {
  return (
    <div>
      <h2>默认仪表盘视图</h2>
      <p>这是硬导航后的回退内容</p>
    </div>
  );
}

// app/dashboard/@sidebar/default.js
export default function DefaultSidebar() {
  return (
    <nav className="sidebar-nav">
      <ul>
        <li><a href="/dashboard">首页</a></li>
        <li><a href="/dashboard/analytics">分析</a></li>
      </ul>
    </nav>
  );
}

2. 路由冲突避免

确保不要同时存在:

  • 具体路由 /chat
  • 可选 catch-all 路由 /chat/[[...id]]

解决方案:

bash 复制代码
# 选择一种路由模式
app/
├── chat/
│   ├── page.js          # /chat
│   └── [id]/
│       └── page.js      # /chat/123

👉点击进入 我的网站

相关推荐
林古5 分钟前
我在 WSL 里控制 Windows Chrome 的一次实战复盘(OpenClaw)
前端
csdn_zhangchunfeng22 分钟前
Qt之slots和Q_SLOTS的区别
开发语言·qt
计算机安禾23 分钟前
【C语言程序设计】第35篇:文件的打开、关闭与读写操作
c语言·开发语言·c++·vscode·算法·visual studio code·visual studio
想不到一个好的ID23 分钟前
Claude Code 初学者必看指南
前端·后端
一枚菜鸟_26 分钟前
04-Flutter状态管理终极指南-Riverpod3.x从入门到精通
前端
一枚菜鸟_29 分钟前
06-Flutter动画从零到炫酷-让你的App动起来
前端
Wect32 分钟前
React Hooks 核心原理
前端·算法·typescript
shughui35 分钟前
Fiddler下载、安装、使用、汉化,详细图文教程(2026附安装包)
前端·测试工具·fiddler
kishu_iOS&AI36 分钟前
Python - 链表浅析
开发语言·python·链表
用户158159637437037 分钟前
多 Agent 系统容错与恢复机制:OAuth 过期、Cron 级联失败的工程解法
javascript