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

👉点击进入 我的网站

相关推荐
warrah2 小时前
前端项目容器化部署问题
前端·docker
GISer_Jing2 小时前
2026前端技术潜在主流前沿方向
前端·人工智能·reactjs
切糕师学AI2 小时前
Vue 中的生命周期钩子
前端·javascript·vue.js
掘金-我是哪吒2 小时前
提升服务器性能,解决前端首页加载过慢的问题
运维·服务器·前端
摘星编程2 小时前
React Native for OpenHarmony 实战:Platform 平台检测与判断
javascript·react native·react.js
暴富暴富暴富啦啦啦2 小时前
使用 v-html 仅渲染新数据的方法
前端·javascript·vue.js
摘星编程2 小时前
React Native for OpenHarmony 实战:Slider 滑块组件使用指南
javascript·react native·react.js
100编程朱老师2 小时前
fping命令详解
开发语言·php
light_in_hand2 小时前
CSS博客
前端·css