Next.js 入门踩坑系列(四)— 路由系统:平行路由与拦截路由

1,734 阅读4分钟

Next.js 入门踩坑系列(一)—初始Nextjs

# Next.js 入门踩坑系列(二)—路由|导航篇

# Next.js 入门踩坑系列(三)—动态路由、路由组

接着上一篇“路由系统:动态路由和路由组”,这篇讲剩下两种——平行路由与拦截路由

3. 平行路由(Parallel Routes)

平行路由是 Next.js 15 中一个非常强大的功能,它允许你在同一个布局中同时或有条件地渲染多个页面。这类似于 Vue 中的插槽功能,非常适合复杂的页面结构。

3.1. 条件渲染

假设你有一个后台管理系统,需要根据用户的登录状态显示不同的页面。你可以使用平行路由来实现:

app
├── layout.js
├── @dashboard
│   └── page.js
└── @login
    └── page.js

layout.js 中,你可以根据用户的登录状态动态渲染页面:

// app/layout.js
import { useRouter } from "next/router";

export default function Layout({ children }) {
  const router = useRouter();
  const isLoggedIn = !!router.query.isLoggedIn; // 假设通过 URL 参数判断登录状态

  return (
    <>
      {isLoggedIn ? children : <Login />}
    </>
  );
}

function Login() {
  return <div>请登录</div>;
}

3.2. 独立路由处理

平行路由还可以为每个路由定义独立的加载和错误处理逻辑。例如,你可以为 @dashboard@login 分别定义加载和错误页面:

app
├── layout.js
├── @dashboard
│   ├── loading.js
│   ├── error.js
│   └── page.js
└── @login
    ├── loading.js
    ├── error.js
    └── page.js

这样,每个路由都可以独立处理加载和错误状态,而不会影响其他路由。

3.3. 子导航

平行路由还可以定义子页面,就像普通的路由一样。例如,你可以在 @dashboard 下添加多个子页面:

app
├── layout.js
├── @dashboard
│   ├── page.js
│   ├── analytics
│   │   └── page.js
│   └── settings
│       └── page.js
└── @login
    └── page.js

这些子页面的 URL 会自动映射,例如 /dashboard/analytics/dashboard/settings

4. 拦截路由(Intercepting Routes)

拦截路由是 Next.js 15 中另一个强大的功能,它允许你在用户访问某个页面之前进行拦截,根据条件重定向到其他页面。这在实现权限控制和登录状态检查时非常有用。

4.1. 未授权跳转

假设你的后台管理系统需要用户登录后才能访问。你可以在 (dashboard) 路由组中添加一个 _middleware.js 文件:

app
├── (dashboard)
│   ├── _middleware.js
│   ├── dashboard
│   │   └── page.js
│   └── settings
│       └── page.js

_middleware.js 中,你可以编写如下代码:

// app/(dashboard)/_middleware.js
import { redirect } from "next/navigation";

export async function middleware(request) {
  const isLoggedIn = request.cookies.get("isLoggedIn");

  if (!isLoggedIn) {
    redirect("/login");
  }
}

当用户未登录时,访问 (dashboard) 下的任何页面都会被重定向到登录页面。

4.2. 根据用户角色跳转

你还可以根据用户的角色进行跳转。例如,普通用户只能访问普通页面,而管理员可以访问管理页面:

// app/(dashboard)/_middleware.js
import { redirect } from "next/navigation";

export async function middleware(request) {
  const isLoggedIn = request.cookies.get("isLoggedIn");
  const role = request.cookies.get("role");

  if (!isLoggedIn) {
    redirect("/login");
  }

  if (role !== "admin" && request.nextUrl.pathname.startsWith("/admin")) {
    redirect("/dashboard");
  }
}

当用户访问 /admin 路径下的页面时,如果其角色不是管理员(admin),则会被重定向到 /dashboard 页面。

4.3. 注意事项

  • 拦截路由只在服务器端执行,不会影响客户端的性能。
  • _middleware.js 文件中,你可以通过 request 对象访问请求信息,例如 request.cookiesrequest.headers 等。
  • 使用 redirect 函数时,可以指定完整的 URL 或相对路径。
  • _middleware.js 文件可以访问 request.nextUrl 对象,其中包含了当前请求的 URL 信息,例如 pathnamesearch 等。

总结

平行路由

  • 条件渲染:根据条件动态渲染不同的页面内容,例如根据用户登录状态显示登录页或主页。
  • 独立路由处理:为每个路由定义独立的加载和错误处理逻辑,提升用户体验。
  • 子导航:为平行路由添加子页面,实现复杂的页面结构,例如后台管理系统的多级菜单。

拦截路由

  • 未授权跳转:在用户未登录时重定向到登录页面,实现权限控制。
  • 根据用户角色跳转:根据用户的角色重定向到不同的页面,实现更细粒度的权限管理。

实际应用场景

1. 博客网站

  • 使用 动态路由/blog/[slug],根据文章标题动态加载内容。
  • 使用 路由组(marketing)(blog),分别管理营销页面和博客页面。
  • 使用 拦截路由:未登录用户访问后台管理页面时重定向到登录页面。

2. 电商网站

  • 使用 动态路由/shop/[...slug],支持多级商品分类。
  • 使用 路由组(shop)(user),分别管理商品页面和用户相关页面。
  • 使用 平行路由:在后台管理页面中,根据用户角色显示不同的模块。

3. 后台管理系统

  • 使用 动态路由/dashboard/[slug],动态加载不同的管理模块。
  • 使用 路由组(admin)(user),分别管理管理员和普通用户的页面。
  • 使用 拦截路由:根据用户权限重定向到不同的页面,实现权限控制。

欢迎订阅我的Nextjs 15专栏,入门必备😋