Parallel Routes
平行路线
Parallel Routing allows you to simultaneously or conditionally render one or more pages in the same layout. For highly dynamic sections of an app, such as dashboards and feeds on social sites, Parallel Routing can be used to implement complex routing patterns.
并行路由允许您同时或有条件地在同一布局中呈现一个或多个页面。对于应用程序的高度动态部分,例如社交网站上的仪表板和提要,并行路由可用于实现复杂的路由模式。
For example, you can simultaneously render the team and analytics pages.
例如,您可以同时呈现团队和分析页面。
Parallel Routing allows you to define independent error and loading states for each route as they're being streamed in independently.
并行路由允许您为每条路由定义独立的错误和加载状态,因为它们是独立流式传输的。
Parallel Routing also allow you to conditionally render a slot based on certain conditions, such as authentication state. This enables fully separated code on the same URL.
并行路由还允许您根据某些条件(例如身份验证状态)有条件地呈现插槽。这可以在同一 URL 上启用完全分离的代码。
Convention
Parallel routes are created using named slots. Slots are defined with the @folder
convention, and are passed to the same-level layout as props.
并行路由是使用命名槽创建的。插槽使用 @folder 约定定义,并传递到与 props 相同级别的布局。
Slots are not route segments and do not affect the URL structure. The file path
/@team/members
would be accessible at/members
.插槽不是路由段,不会影响 URL 结构。文件路径 /@team/members 可以在 /members 访问。
For example, the following file structure defines two explicit slots: @analytics
and @team
.
例如,以下文件结构定义了两个显式槽:@analytics 和@team。
The folder structure above means that the component in app/layout.js
now accepts the @analytics
and @team
slots props, and can render them in parallel alongside the children
prop:
上面的文件夹结构意味着 app/layout.js 中的组件现在接受 @analytics 和 @team slots 属性,并且可以与 children 属性一起并行渲染它们:
app/layout.tsx
javascript
export default function Layout(props: { children: React.ReactNode; analytics: React.ReactNode; team: React.ReactNode;}) { return ( <> {props.children} {props.team} {props.analytics} </> );}
Good to know: The
children
prop is an implicit slot that does not need to be mapped to a folder. This meansapp/page.js
is equivalent toapp/@children/page.js
.提示:children 属性是一个隐式插槽,不需要映射到文件夹。这意味着 app/page.js 等同于 app/@children/page.js。
Unmatched Routes
无与伦比的路线
By default, the content rendered within a slot will match the current URL.
默认情况下,插槽中呈现的内容将与当前 URL 匹配。
In the case of an unmatched slot, the content that Next.js renders differs based on the routing technique and folder structure.
在插槽不匹配的情况下,Next.js 呈现的内容因路由技术和文件夹结构而异。
default.js
默认.js
You can define a default.js
file to render as a fallback when Next.js cannot recover a slot's active state based on the current URL.
当 Next.js 无法根据当前 URL 恢复插槽的活动状态时,您可以定义一个 default.js 文件作为后备呈现。
Consider the following folder structure. The @team
slot has a settings
directory, but @analytics
does not.
考虑以下文件夹结构。 @team 插槽有一个设置目录,但@analytics 没有。
If you were to navigate from the root /
to /settings
, the content that gets rendered is different based on the type of navigation and the availability of the default.js
file.
如果您要从根 / 导航到 /settings,根据导航类型和 default.js 文件的可用性,呈现的内容会有所不同。
With @analytics/default.js |
Without @analytics/default.js |
|
Soft Navigation | @team/settings/page.js and @analytics/page.js |
@team/settings/page.js and @analytics/page.js |
Hard Navigation | @team/settings/page.js and @analytics/default.js |
404 |
Soft Navigation
软导航
On a soft navigation - Next.js will render the slot's previously active state, even if it doesn't match the current URL.
在软导航上 - Next.js 将呈现广告位先前的活动状态,即使它与当前 URL 不匹配。
Hard Navigation
硬导航
On a hard navigation - a navigation that requires a full page reload - Next.js will first try to render the unmatched slot's default.js
file. If that's not available, a 404 gets rendered.
在硬导航(需要重新加载整页的导航)中,Next.js 将首先尝试呈现不匹配的插槽的 default.js 文件。如果这不可用,则会呈现 404。
The 404 for unmatched routes helps ensure that you don't accidentally render a route that shouldn't be parallel rendered.
不匹配路由的 404 有助于确保您不会意外渲染不应并行渲染的路由。
useSelectedLayoutSegment(s)
在 SelectedLayoutSegment(s)
Both useSelectedLayoutSegment
and useSelectedLayoutSegments
accept a parallelRoutesKey
, which allows you read the active route segment within that slot.
useSelectedLayoutSegment 和 useSelectedLayoutSegments 都接受一个 parallelRoutesKey,它允许您读取该插槽中的活动路由段。
app/layout.tsx
"use client";import { useSelectedLayoutSegment } from "next/navigation"; export default async function Layout(props: { ... authModal: React.ReactNode;}) { const loginSegments = useSelectedLayoutSegment("authModal") ...}
When a user navigates to @authModal/login
, or /login
in the URL bar, loginSegments
will be equal to the string "login"
.
当用户导航到 @authModal/login 或 URL 栏中的 /login 时,loginSegments 将等于字符串“login”。
Examples
例子
Modals
模态
Parallel Routing can be used to render modals.
并行路由可用于渲染模态。
The @authModal
slot renders a<Modal>
component that can be shown by navigating to a matching route, for example /login
.
@authModal 插槽呈现一个 组件,可以通过导航到匹配的路由(例如 /login)来显示该组件。
app/layout.tsx
export default async function Layout(props: { ... authModal: React.ReactNode;}) { return ( <> ... {props.authModal} </> );}
app/@authModal/login/page.tsx
import { Modal } from 'components/modal'; export default function Login() { return ( <Modal> <h1>Login</h1> ... </Modal> );}
To ensure that the contents of the modal don't get rendered when it's not active, you can create a default.js
file that returns null
.
为确保模式的内容在未处于活动状态时不会呈现,您可以创建一个返回 null 的 default.js 文件。
app/@authModal/login/default.tsx
javascript
复制代码
exportdefaultfunctionDefault() { returnnull;}
Dismissing a modal
关闭模态
If a modal was initiated through client navigation, e.g. by using <Link href="/login">
, you can dismiss the modal by calling router.back()
or by using a Link
component.
如果模式是通过客户端导航启动的,例如通过使用 ,您可以通过调用 router.back() 或使用 Link 组件关闭模态。
app/@authModal/login/page.tsx
'use client';import { useRouter } from 'next/navigation';import { Modal } from 'components/modal'; export default async function Login() { const router = useRouter(); return ( <Modal> <span onClick={() => router.back()}>Close modal</span> <h1>Login</h1> ... </Modal> );} More information on modals is covered in the Intercepting Routes section.
有关模式的更多信息,请参阅拦截路由部分。
If you want to navigate elsewhere and dismiss a modal, you can also use a catch-all route.
如果你想导航到别处并关闭模态,你也可以使用 catch-all 路由。
app/@authModal/[...catchAll]/page.js
export default function CatchAll() { return null;}
Catch-all routes take presedence over
default.js
.Catch-all 路由优先于 default.js。
Conditional Routes
条件路由
Parallel Routes can be used to implement conditional routing. For example, you can render a @dashboard
or @login
route depending on the authentication state.
Parallel Routes 可用于实现条件路由。例如,您可以根据身份验证状态呈现 @dashboard 或 @login 路由。
app/layout.tsx
import { getUser } from '@/lib/auth'; export default function Layout({ params, dashboard, login }) { const isLoggedIn = getUser(); return isLoggedIn ? dashboard : login;}
Intercepting Routes
拦截路线
Intercepting routes allows you to load a route within the current layout while keeping the context for the current page. This routing paradigm can be useful when you want to "intercept" a certain route to show a different route.
拦截路由允许您在当前布局中加载路由,同时保留当前页面的上下文。当您想“拦截”某条路线以显示不同的路线时,此路由范例会很有用。
For example, when clicking on a photo from within a feed, a modal overlaying the feed should show up with the photo. In this case, Next.js intercepts the /feed
route and "masks" this URL to show /photo/123
instead.
例如,当从提要中单击照片时,覆盖提要的模式应该与照片一起显示。在这种情况下,Next.js 拦截 /feed 路由并“屏蔽”此 URL 以显示 /photo/123。
However, when navigating to the photo directly by for example when clicking a shareable URL or by refreshing the page, the entire photo page should render instead of the modal. No route interception should occur.
然而,当直接导航到照片页面时,例如通过单击可共享的URL或刷新页面时,应该渲染整个照片页面而不是模态框。不应进行路由拦截。
Convention
Intercepting routes can be defined with the (..)
convention, which is similar to relative path convention ../
but for segments.
拦截路由可以使用 (..) 约定来定义,这类似于相对路径约定 ../ 但用于段。
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 rootapp
directory- (...) 匹配根应用程序目录中的段
For example, you can intercept the photo
segment from within the feed
segment by creating a (..)photo
directory.
例如,您可以通过创建 (..)photo 目录从提要段中拦截照片段。
Note that the
(..)
convention is based on route segments, not the file-system.请注意, (..) 约定基于路由段,而不是文件系统。
Examples
Modals
模态
Intercepting Routes can be used together with Parallel Routes to create modals.
拦截路由可以与并行路由一起使用来创建模态。
Using this pattern to create modals overcomes some common challenges when working with modals, by allowing you to:
使用此模式创建模态可以克服使用模态时的一些常见挑战,它允许您:
- Make the modal content shareable through a URL
- 让模态内容可以通过URL共享
- Preserve context when the page is refreshed, instead of closing the modal
- 在页面刷新时保留上下文,而不是关闭模态
- Close the modal on backwards navigation rather than going to the previous route
- 在向后导航时关闭模态,而不是转到前面的路线
- Reopen the modal on forwards navigation
- 重新打开前向导航的模式
In the above example, the path to the
photo
segment can use the(..)
matcher since@modal
is a slot and not a segment. This means that thephoto
route is only one segment level higher, despite being two file-system levels higher.在上面的示例中,照片片段的路径可以使用 (..) 匹配器,因为 @modal 是一个插槽而不是片段。这意味着照片路由只高了一个段级别,尽管它是两个文件系统级别。
Other examples could include opening a login modal in a top navbar while also having a dedicated /login
page, or opening a shopping cart in a side modal.
其他示例可能包括在顶部导航栏中打开登录模式,同时还具有专用的 /login 页面,或在侧面模式中打开购物车。
View an example of modals with Intercepted and Parallel Routes.
查看示例
具有拦截和平行路线的模态。