ZQ
About 1866 wordsAbout 6 min
reactNextJs
2024-7-10
This note records things about Parallel Routes.
“并行路由”允许您在同一布局中同时或有条件地呈现一个或多个页面。它们对于应用的高度动态部分非常有用,例如社交网站上的仪表板和源。
例如,考虑仪表板,您可以使用并行路由同时呈现 team
和 analytics
页面:
➜ parallelRoutes git:(0ab53bc) tree
.
├── @analytics
│ └── page.tsx
├── layout.tsx
├── page.tsx
└── @team
└── page.tsx
3 directories, 4 files
app-router
对应的位置添加了平行路由demo,效果如图。
使用命名时隙创建并行路由。插槽是按照 @folder
约定定义的。例如,以下文件结构定义了两个插槽: @analytics
和 @team
:
插槽作为道具传递到共享父布局。对于上面的例子,组件 app/layout.js
现在接受 @analytics
和 @team
slot 道具,并且可以与 children
prop 并行渲染它们:
export default function Layout({
children,
team,
analytics,
}: {
children: React.ReactNode
analytics: React.ReactNode
team: React.ReactNode
}) {
return (
<>
{children}
{team}
{analytics}
</>
)
}
但是,插槽不是路由段,不会影响 URL 结构。例如,对于 /@analytics/views
,URL 将是 /views
因为 @analytics
是一个插槽。
Tips:
children
prop 是一个不需要映射到文件夹的隐式插槽。此均值 app/page.js
等价于 app/@children/page.js
。默认情况下,Next.js 会跟踪每个插槽的活动状态(或子页面)。但是,在插槽中呈现的内容将取决于导航类型:
软导航(Soft Navigation):
硬导航(Hard Navigation):
Tips:
404
对于不匹配的路由有助于确保您不会意外地在页面上呈现并行路由。default.js
您可以定义一个 default.js
文件,作为初始加载或整页重新加载期间不匹配插槽的回退。
请考虑以下文件夹结构。 @team
插槽有一个 /settings
页面,但 @analytics
没有。
导航到 /settings
时, @team
插槽将呈现 /settings
页面,同时维护 @analytics
插槽的当前活动页面。
刷新时 Next.js
将为 @analytics
渲染 default.js
。如果 default.js
不存在,则会渲染 404
。
此外,由于 children
是一个隐式插槽,因此您还需要创建一个 default.js
文件, children
以便在Next.js
无法恢复父页面的活动状态时呈现回退。
useSelectedLayoutSegments
useSelectedLayoutSegment
和 useSelectedLayoutSegments
都接受 parallelRoutesKey
参数,该参数允许您读取槽内的活动路线段。
'use client'
import { useSelectedLayoutSegment } from 'next/navigation'
export default function Layout({ auth }: { auth: React.ReactNode }) {
const loginSegment = useSelectedLayoutSegment('auth')
// ...
}
当用户导航到 app/@auth/login
(或 URL 栏中的 /login
)时, loginSegment
将等于字符串 "login"
。
const loginSegment = useSelectedLayoutSegment('auth')
:
useSelectedLayoutSegment
钩子获取名为 auth
的插槽的当前活动路由段,并将其存储在 loginSegment
变量中。您可以使用并行路由根据某些条件(例如用户角色)有条件地渲染路由。例如,要为 /admin
或 /user
角色呈现不同的仪表板页面
import { checkUserRole } from '@/lib/auth'
export default function Layout({
user,
admin,
}: {
user: React.ReactNode
admin: React.ReactNode
}) {
const role = checkUserRole()
return <>{role === 'admin' ? admin : user}</>
}
您可以在槽内添加 layout
以允许用户独立导航该槽。这对于创建选项卡很有用。
例如, @analytics
插槽有两个子页面: /page-views
和 /visitors
。
在 @analytics
中,创建一个 layout
文件以在两个页面之间共享选项卡:
import Link from 'next/link'
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<nav>
<Link href="/page-views">Page Views</Link>
<Link href="/visitors">Visitors</Link>
</nav>
<div>{children}</div>
</>
)
}
并行路由可以与拦截路由一起使用来创建模态。这使您可以解决构建模式时的常见挑战,例如:
考虑以下 UI 模式,用户可以使用客户端导航从布局打开登录模式,或访问单独的 /login
页面:
要实现此模式,首先创建一个用于呈现主登录页面的 /login
路由。
import { Login } from '@/app/ui/login'
export default function Page() {
return <Login />
}
然后,在 @auth
槽内添加返回 null
的 default.js
文件。这可确保模态在不活动时不会呈现。
export default function Default() {
return null
}
在您的 @auth
插槽中,通过更新 /(.)login
文件夹来拦截 /login
路由。将 <Modal>
组件及其子组件导入到 /(.)login/page.tsx
文件中:
import { Modal } from '@/app/ui/modal'
import { Login } from '@/app/ui/login'
export default function Page() {
return (
<Modal>
<Login />
</Modal>
)
}
拦截路由允许您从当前布局内应用程序的其他部分加载路由。当您想要显示路由内容而不需要用户切换到不同的上下文时,此路由范例非常有用。
例如,当单击源中的照片时,您可以在模式中显示照片,覆盖源。在这种情况下,Next.js 拦截 /photo/123
路由,屏蔽 URL,并将其覆盖在 /feed
上。
但是,当通过单击可共享 URL 或刷新页面导航到照片时,应呈现整个照片页面而不是模式。不应发生路由拦截。
拦截路由可以使用 (..)
约定来定义,它类似于相对路径约定 ../
,但针对的是段。
You can use: 您可以使用:
(.)
to match segments on the same level(..)
to match segments one level above(..)(..)
to match segments two levels above(...)
to match segments from the root app
directory例如,您可以通过创建 (..)photo
目录从 feed
段中拦截 photo
段。
考虑以下 UI 模式,用户可以使用客户端导航从图库中打开照片模式,或直接从可共享 URL 导航到照片页面:
在上面的示例中, photo
段的路径可以使用 (..)
匹配器,因为 @modal
是一个槽而不是一个段。这意味着 photo
路由仅高一级段,尽管文件系统级别高两级。