拦截路由(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.tsx
和layout.tsx
的辅助,才能最终完成整体的效果;
default.tsx
部分
- 并行路由:default.js
- 文件约定:default.js
layout.tsx
部分
在要进行拦截的路由下建立(就像上面的/search
路由下要拦截/pins/[id]
这种情景下);
建立layout
文件的目的
是为了拦截路由后的呈现
(为目标路由
内容呈现预留“插槽”
位置)
// file: app/(root)/search/layout.tsximport 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》项目上