拦截路由(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: ^18next: 14.2.20tailwindcss: ^3.4.1typescript: ^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.tsx和layout.tsx的辅助,才能最终完成整体的效果;

default.tsx部分

并行路由:default.js文件约定:default.js

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》项目上