【NextJS】路由之平行路由(Parallel Routes)

在这里插入图片描述

Parallel Routes 特性

  • 同时或条件渲染:
    能够在同一布局中同时或依据条件渲染一个或多个页面,这对于应用中像仪表盘、社交网站动态消息等高度动态的部分非常有用。例如,可以同时在一个布局中展示团队相关页面和分析相关页面。(类似于 Vue 的插槽功能)
  • 基于命名插槽创建:
    通过@文件夹约定来定义命名插槽,如@analytics@team等,这些插槽作为属性传递给共享的父布局组件,父布局可以在渲染时将其与children属性一起并行处理。
  • 导航特性
    • 软导航(Soft Navigation):
      在客户端导航时,执行部分渲染,仅更改插槽内的子页面,其他插槽的活动子页面保持不变,即使它们与当前 URL 不匹配。
    • 硬导航(Hard Navigation):
      全页加载(浏览器刷新)后,Next.js 无法确定与当前 URL 不匹配的插槽的活动状态,此时将为不匹配的插槽渲染default.js文件(若存在),否则渲染 404。
  • 不影响 URL 结构:
    插槽不是路由段,不会影响 URL 的结构,例如/@analytics/views的实际 URL 为/views
  • 隐式插槽与回退机制:
    children属性是隐式插槽,app/page.js等同于app/@children/page.js。可为不匹配的插槽在初始加载或全页重新加载时定义default.js文件作为回退渲染内容,对于children隐式插槽也需创建default.js文件作为父页面活动状态无法恢复时的回退。
  • 灵活的应用场景
    • 条件路由(Conditional Routes):
      可以根据不同条件(如用户角色)有条件地渲染路由,比如为不同角色展示不同的仪表盘页面。
    • 选项卡组(Tab Groups):
      在插槽内添加布局,使用户能够独立导航插槽,适用于创建选项卡功能,例如在@analytics插槽内创建布局来实现两个子页面的选项卡效果。
    • 模态框(Modals):
      结合拦截路由(Intercepting Routes)可创建模态框,解决模态框构建中的多个常见问题,如通过 URL 共享模态内容、页面刷新时保留上下文、向后导航时关闭模态框、向前导航时重新打开模态框等。
  • 特定函数支持: useSelectedLayoutSegment(s)函数接受parallelRoutesKey参数,用于读取插槽内的活动路由段。

**[注]:** 看前请先查看【官方文档内容】后再回过头看以下内容!!

以下实践较复杂下的路由组合下进行特性探究

实验环境

  • next: 15.0.3
  • react: 19.0.0-rc-66855b96-20241106
  • tailwindcss: ^3.4.15
  • typescript: ^5

目录结构

|- app
	|- (groups)
		|- product
			|- @details
				|- [pid]
					|- topic
						|- [tid]
							|- page.tsx
					|- page.tsx
				|- default.tsx
			|- [pid]
				|- topic
					|- [tid]
						|- page.tsx
				|- page.tsx
			|- layout.tsx
	|- about
		|- page.tsx
	|- layout.tsx
	|- page.tsx
|- public
// ...

以上目录涉及两大知识点:路由(Routing)文件约定(File Conventions)

路由:

文件约定:

实践

以下内容的card组件主要是为了方便看清整个Parallel Routes的链路过程,自定义封装的非必要内容

页面

产品入口(首页)页面布局:app/(groups)/product/layout.tsx

// file: app/layout.tsx

import Card from "@/components/Card";

const ProductLayout = function ({children, details}: Readonly<{
    children: React.ReactNode;
    details?: React.ReactNode; // 这里定义一个插槽名称(与@details目录命名一致)
}>) {
    return (
        <Card title={"Product Layout"}>
            {children}
            {details}
        </Card>
    )
}

export default ProductLayout;

产品详情页面:app/(groups)/product/[pid]/page.tsx

// file: app/(groups)/product/[pid]/page.tsx

import Card from "@/components/Card";

const Page = function () {
    return (
        <Card title={"product/[pid]/page"} className={"mb-5"}>
            Page Content
        </Card>
    )
}

export default Page

@details详情页面:app/(groups)/product/[pid]/page.tsx

// file: app/(groups)/product/[pid]/page.tsx

import Card from "@/components/Card";

const Page = function () {
    return (
        <Card title={"product/[pid]/page"} className={"mb-5"}>
            Page Content
        </Card>
    )
}

export default Page

@details回退页面:app/(groups)/product/default.tsx

// file: app/(groups)/product/default.tsx
// doc: https://nextjs.org/docs/app/building-your-application/routing/parallel-routes#defaultjs

const AnalyticsViewPage = function () {
    return null
}

export default AnalyticsViewPage;

访问
url: /product/pid_xxxxxx
在这里插入图片描述

平行路由与页面路由对应关系:

假定在同个布局文件中,放置@details这个插槽

页面路由(product/[pid]/page) ----会与----> 平行路由(product/@details/[pid]/page)进行配对关联

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

转悠的陀螺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值