【NextJS】路由之拦截路由(Intercepting Routes) - 简仿花瓣网

发布于:2024-12-18 ⋅ 阅读:(38) ⋅ 点赞:(0)

在这里插入图片描述

拦截路由(Intercepting Routes)

@link: https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes

  • 概念
    拦截路由允许在当前布局中加载应用程序其他部分的路由,即在不切换用户上下文的情况下显示路由内容。例如,在信息流中点击照片时,可以在模态框中显示照片,覆盖信息流,此时 Next.js 拦截 /photo/123 路由,掩盖 URL 并覆盖在 /feed 上。

  • 路由约定(路由文件夹结构)
    以特定的文件夹结构来组织拦截路由相关的代码。

    • 使用 (..) 约定来定义拦截路由,类似于相对路径约定 ../ 但用于路由段。

      • (.) 匹配同一级别的段,(..) 匹配上一级别的段,
      • (..)(..) 匹配上两级别的段,
      • (...) 匹配从根应用目录开始的段。


      例如,可通过创建 (..)photo 目录从 feed 段中拦截 photo 段。
      注:该约定基于路由段而非文件系统。

注意导航方式

  • 软导航
    通过点击信息流中的照片等客户端导航方式,在模态框中显示内容,此时进行路由拦截。
  • 硬导航
    通过点击可分享 URL 或刷新页面导航到照片时,应渲染整个照片页面,不进行路由拦截。

实践中认识

直观效果: 可以参见“花瓣网”的图片列表->图片详情的样式与路由变化

下面简单仿制花瓣网界面布局用于认识NextJS拦截路由(Intercepting Routes)

准备环境

  • react: ^18
  • next: 14.2.20
  • tailwindcss: ^3.4.1
  • typescript: ^5

在这里插入图片描述
页面样式跳过,文末有完整项目代码

目录结构

app目录下目录结构准备

在这里插入图片描述

代码

效果表现

示例效果
步骤:

  • 从列表随机选择一个进入详情页
  • 此时详情页的路由地址被打开 (注: 此时样式类似Modal 对话框的表现形式,层叠原有列表页面上)
  • 当重新刷新页面时,似乎进到了“全新的页面”上

这种表现形式,在Next.js框架中称为拦截路由(Intercepting Routes)

重点部分

在上面目录结构上,是否好奇search目录下的@modal(..)pins这类奇奇怪怪的目录名称?下面重点解释解释

  • @modal命名粗暴理解的话也可以当作是路由组的另一种表达形式(规则:@ + [name] 命名)
    也就是《Parallel Routes:Tab Groups》,并行路由里提到的标签组的概念;

  • (..)pins命名就是拦截路由的关键了,这里表达的是:

    • 在上游是/search路由下访问/pins/[id]路由的拦截指向
    • pins目录和search是同级的,则../pins就可以找到(类似文件系统里的相对路径)
    • 注:@[name]规则的目录是被忽略层级
      并且拦截路径要和目标路由路径保持一致(例:(..)pins/[id]pins/[id])

除了上面两部分特殊命名外,还需要default.tsxlayout.tsx的辅助,才能最终完成整体的效果;

default.tsx部分

layout.tsx部分

在要进行拦截的路由下建立(就像上面的/search路由下要拦截/pins/[id]这种情景下);

建立layout文件的目的是为了拦截路由后的呈现(为目标路由内容呈现预留“插槽”位置)

// file: app/(root)/search/layout.tsx

import type {ReactNode} from "react";

const PageLayout = function (props: Readonly<{
    children: ReactNode,
    modal: ReactNode
}>) {
    const {children, modal} = props;

    return (
        <>
            {children}
            {modal}
        </>
    )
}

export default PageLayout;

至此几个要点部分应该都说到了,有啥不足评论区里一起探讨探讨!

完整代码可移步到《GitCode: demo-Intercepting-routes》项目上