一看就会的Next.js App Router版 -- Routing(上)(一)

简介: 一看就会的Next.js App Router版 -- Routing

Routing Fundamentals

每个应用程序的骨架都是路由。这一页将向你介绍网络路由的基本概念,以及如何在Next.js中处理路由。

Terminology

首先,您将看到这些术语在整个文档中使用。这里有一个快速参考:

image.png

  • Tree:  A convention for visualizing a hierarchical structure. For example, a component tree with parent and children components, a folder structure, etc.
  • Subtree:  Part of a tree, starting at a new root (first) and ending at the leaves (last).
  • Root: The first node in a tree or subtree, such as a root layout.
  • Leaf:  Nodes in a subtree that have no children, such as the last segment in a URL path.
  • URL Segment:  Part of the URL path delimited by slashes.Part of the URL path delimited by slashes. URL路径的一部分,用斜杠分隔
  • URL Path:  Part of the URL that comes after the domain (composed of segments). 域名之后的URL的一部分(由段组成)。

image.png

The app Directory

In version 13, Next.js introduced a new App Router built on React Server Components, which supports shared layouts, nested routing, loading states, error handling, and more.

在版本 13 中,Next.js 引入了一个基于 React Server Components 构建的新 App Router,它支持共享布局、嵌套路由、加载状态、错误处理等。

The App Router works in a new directory named app. The app directory works alongside the pages directory to allow for incremental adoption. This allows you to opt some routes of your application into the new behavior while keeping other routes in the pages directory for previous behavior. If your application uses the pages directory, please also see the Pages Router documentation.

App Router 在一个名为 app 的新目录中工作。 app 目录与 pages 目录一起工作以允许增量采用。这允许您将应用程序的某些路由选择为新行为,同时将其他路由保留在页面目录中以用于先前的行为。如果您的应用程序使用 pages 目录,另请参阅 Pages Router 文档。

Good to know: The App Router takes priority over the Pages Router. Routes across directories should not resolve to the same URL path and will cause a build-time error to prevent a conflict.

提示:App Router 优先于 Pages Router。跨目录的路由不应解析为相同的 URL 路径,并且会导致构建时错误以防止冲突。

image.png

By default, components inside app are React Server Components. This is a performance optimization and allows you to easily adopt them, and you can also use Client Components.

默认情况下,app 中的组件是 React Server Components。这是一种性能优化,可以让您轻松采用它们,您还可以使用客户端组件。

Recommendation: Check out the Server and Client Components page if you're new to Server Components.

建议:如果您不熟悉服务器组件,请查看服务器和客户端组件页面。

Roles of Folders and Files

文件夹和文件的作用

In the App Router:

在应用路由器中:

  • Folders are used to define routes. A route is a single path of nested folders, following the hierarchy from the root folder down to a final leaf folder that includes a page.js file.
  • 文件夹用于定义路线。路由是嵌套文件夹的单个路径,遵循从根文件夹到包含 page.js 文件的最终叶文件夹的层次结构。
  • Files are used to create UI that is shown for the route segment. See special files.
  • 文件用于创建为路线段显示的 UI。见特殊文件。

Route Segments

路线段

Each folder in a route represents a route segment. Each route segment is mapped to a corresponding segment in a URL path.

路线中的每个文件夹代表一个路线段。每个路由段都映射到 URL 路径中的相应段。

image.png

Nested Routes

嵌套路由

To create a nested route, you can nest folders inside each other. For example, you can add a new /dashboard/settings route by nesting two new folders in the app directory.

要创建嵌套路由,您可以将文件夹相互嵌套。例如,您可以通过在 app 目录中嵌套两个新文件夹来添加新的 /dashboard/settings 路由。

The /dashboard/settings route is composed of three segments:

/dashboard/settings 路由由三个部分组成:

  • / (Root segment) /(根段)
  • dashboard (Segment) 仪表板(部分)
  • settings (Leaf segment) 设置(叶段)

File Conventions

Next.js 提供了一组特殊文件来创建在嵌套路由中具有特定行为的 UI:

page.js: Create the unique UI of a route and make the path publicly accessible.

  • route.js: Create server-side API endpoints for a route.

page.js:创建路由的唯一 UI 并使路径可公开访问。

  • route.js:为路由创建服务器端 API 端点。

layout.js: Create shared UI for a segment and its children. A layout wraps a page or child segment.

  • template.js: Similar to layout.js, except a new component instance is mounted on navigation. Use layouts unless you need this behavior.

layout.js:为段及其子段创建共享 UI。布局包裹页面或子段。

  • template.js:类似于layout.js,只是在navigation上挂载了一个新的组件实例。除非您需要这种行为,否则请使用布局。

loading.js: Create loading UI for a segment and its children. loading.js wraps a page or child segment in a React Suspense Boundary, showing the loading UI while they load.

  • loading.js:为片段及其子片段创建加载 UI。 loading.js 在 React Suspense Boundary 中包装页面或子段  ,在加载时显示加载 UI。

error.js: Create error UI for a segment and its children. error.js wraps a page or child segment in a React Error Boundary, showing the error UI if an error is caught.

  • global-error.js: Similar to error.js, but specifically for catching errors in the root layout.js.

error.js:为段及其子段创建错误 UI。 error.js 将页面或子段包装在 React 错误边界中如果捕获到错误,则显示错误 UI。

  • global-error.js:类似于 error.js,但专门用于捕获根 layout.js 中的错误。

not-found.js: Create UI to show when the notFound function is thrown within a route segment or when a URL is not matched by any route.

not-found.js:创建 UI 以显示何时在路由段内抛出 notFound 函数或何时 URL 与任何路由都不匹配。

Good to know:.js, .jsx, or .tsx file extensions can be used for special files.

提示:.js、.jsx 或 .tsx 文件扩展名可用于特殊文件。

Component Hierarchy

组件层次结构

The React components defined in special files of a route segment are rendered in a specific hierarchy:

在路由段的特殊文件中定义的 React 组件在特定的层次结构中呈现:

  • layout.js
  • 布局.js
  • template.js
  • 模板.js
  • error.js (React error boundary)
  • error.js(反应错误边界)
  • loading.js (React suspense boundary)
  • loading.js(React悬念边界)
  • not-found.js (React error boundary)
  • not-found.js(反应错误边界)
  • page.js or nested layout.js
  • page.js 或嵌套 layout.js

image.png

In a nested route, the components of a segment will be nested inside the components of its parent segment.

在嵌套路由中,段的组件将嵌套在其父段的组件内。

image.png

Colocation

托管

In addition to special files, you have the option to colocate your own files inside folders. For example, stylesheets, tests, components, and more.

除了特殊文件之外,您还可以选择将自己的文件放在文件夹中。例如,样式表、测试、组件等。

image.png

Server-Centric Routing with Client-side Navigation

具有客户端导航的以服务器为中心的路由

Unlike the pages directory which uses client-side routing, the App Router uses server-centric routing to align with Server Components and data fetching on the server. With server-centric routing, the client does not have to download a route map and the same request for Server Components can be used to look up routes. This optimization is useful for all applications, but has a larger impact on applications with many routes.

与使用客户端路由的页面目录不同,App Router 使用以服务器为中心的路由来与服务器上的服务器组件和数据获取保持一致。使用以服务器为中心的路由,客户端不必下载路由映射,并且可以使用对服务器组件的相同请求来查找路由。此优化对所有应用程序都有用,但对具有许多路由的应用程序影响更大。

Although routing is server-centric, the router uses client-side navigation with the Link Component - resembling the behavior of a Single-Page Application. This means when a user navigates to a new route, the browser will not reload the page. Instead, the URL will be updated and Next.js will only render the segments that change.

尽管路由是以服务器为中心的,但路由器使用带有链接组件的客户端导航——类似于单页应用程序的行为。这意味着当用户导航到新路由时,浏览器不会重新加载页面。相反,URL 将被更新并且 Next.js 将只呈现更改的段。

Additionally, as users navigate around the app, the router will store the result of the React Server Component payload in an in-memory client-side cache. The cache is split by route segments which allows invalidation at any level and ensures consistency across React's concurrent renders. This means that for certain cases, the cache of a previously fetched segment can be re-used, further improving performance.

此外,当用户在应用程序中导航时,路由器会将 React 服务器组件负载的结果存储在内存中的客户端缓存中。缓存由路由段分割,允许在任何级别失效并确保 React 的并发渲染之间的一致性。这意味着在某些情况下,可以重新使用先前获取的段的缓存,从而进一步提高性能。

Checkout the Linking and Navigating page to learn how to use the Link component.

查看链接和导航页面以了解如何使用链接组件。

Partial Rendering

局部渲染

When navigating between sibling routes (e.g. /dashboard/settings and /dashboard/analytics below), Next.js will only fetch and render the layouts and pages in routes that change. It will not re-fetch or re-render anything above the segments in the subtree. This means that in routes that share a layout, the layout will be preserved when a user navigates between sibling pages.

在同级路由之间导航时(例如下面的 /dashboard/settings 和 /dashboard/analytics),Next.js 将只获取和渲染路由中发生变化的布局和页面。它不会重新获取或重新呈现子树中段上方的任何内容。这意味着在共享布局的路由中,当用户在同级页面之间导航时,布局将被保留。

image.png

Without partial rendering, each navigation would cause the full page to re-render on the server. Rendering only the segment that’s updating reduces the amount of data transferred and execution time, leading to improved performance.

如果没有部分呈现,每次导航都会导致整个页面在服务器上重新呈现。仅渲染正在更新的片段可减少传输的数据量和执行时间,从而提高性能。

Advanced Routing Patterns

高级路由模式

The App Router also provides a set conventions to help you implement more advanced routing patterns. These include:

App Router 还提供了一组约定来帮助您实现更高级的路由模式。这些包括:

  • Parallel Routes: Allow you to simultaneously show two or more pages in the same view that can be navigated independently. You can use them for split views that have their own sub-navigation. E.g. Dashboards.
  • 并行路由:允许您在同一视图中同时显示两个或多个可以独立导航的页面。您可以将它们用于具有自己的子导航的拆分视图。例如。仪表板。
  • Intercepting Routes: Allow you to intercept a route and show it in the context of another route. You can use these when keeping the context for the current page is important. E.g. Seeing all tasks while editing one task or expanding a photo in a feed.
  • 拦截路线
    :允许您截取一条路线并将其显示在另一条路线的上下文中。当保持当前页面的上下文很重要时,您可以使用它们。例如。在编辑一个任务或展开提要中的一张照片时查看所有任务。

These patterns allow you to build richer and more complex UIs, democratizing features that were historically complex for small teams and individual developers to implement.

这些模式允许您构建更丰富和更复杂的 UI,使小型团队和个人开发人员过去难以实现的功能民主化。

Defining Routes

We recommend reading the Routing Fundamentals page before continuing.

我们建议在继续之前阅读路由基础知识页面。

This page will guide you through how to define and organize routes in your Next.js application.

此页面将指导您完成如何在 Next.js 应用程序中定义和组织路由。

Creating Routes

创建路线

Inside the app directory, folders are used to define routes.

在 app 目录中,文件夹用于定义路由。

Each folder represents a route segment that maps to a URL segment. To create a nested route, you can nest folders inside each other.

每个文件夹代表一个映射到 URL 段的路由段。要创建嵌套路由,您可以将文件夹相互嵌套。

image.png

A special page.js file is used to make route segments publicly accessible.

一个特殊的 page.js 文件用于使路由段可公开访问。

image.png

In this example, the /dashboard/analytics URL path is not publicly accessible because it does not have a corresponding page.js file. This folder could be used to store components, stylesheets, images, or other colocated files.

在此示例中,/dashboard/analytics URL 路径不可公开访问,因为它没有对应的 page.js 文件。此文件夹可用于存储组件、样式表、图像或其他位于同一位置的文件。

Good to know:.js, .jsx, or .tsx file extensions can be used for special files.

提示:.js、.jsx 或 .tsx 文件扩展名可用于特殊文件。

Creating UI

创建用户界面

Special file conventions are used to create UI for each route segment. The most common are pages to show UI unique to a route, and layouts to show UI that is shared across multiple routes.

特殊文件约定用于为每个路由段创建 UI。最常见的是显示路由特有 UI 的页面,以及显示跨多个路由共享的 UI 的布局。

For example, to create your first page, add a page.js file inside the app directory and export a React component:

例如,要创建您的第一个页面,请在 app 目录中添加一个 page.js 文件并导出一个 React 组件:

app/page.js

export default function Page() {  return <h1>Hello, Next.js!</h1>;}

Learn more about creating pages and layouts.

了解有关创建页面和布局的更多信息。

Pages and Layouts

We recommend reading the Routing Fundamentals and Defining Routes pages before continuing.

我们建议在继续之前阅读路由基础知识和定义路由页面。

The App Router inside Next.js 13 introduced new file conventions to easily create pages, shared layouts, and templates. This page will guide you through how to use these special files in your Next.js application.

Next.js 13 中的 App Router 引入了新的文件约定,可以轻松创建页面、共享布局和模板。本页将指导您了解如何在 Next.js 应用程序中使用这些特殊文件。

Pages

A page is UI that is unique to a route. You can define pages by exporting a component from a page.js file. Use nested folders to define a route and a page.js file to make the route publicly accessible.

页面是路由特有的 UI。您可以通过从 page.js 文件导出组件来定义页面。使用嵌套文件夹定义路由和 page.js 文件以使路由可公开访问。

Create your first page by adding a page.js file inside the app directory:

通过在 app 目录中添加 page.js 文件来创建您的第一个页面:

image.png

app/page.js
// `app/page.js` is the UI for the root `/` URL
export default function Page() {  return <h1>Hello, Next.js!</h1>;}

Good to know:

  • A page is always the leaf of the route subtree.
  • 页面始终是路由子树的叶子。
  • .js, .jsx, or .tsx file extensions can be used for Pages.
  • .js、.jsx 或 .tsx 文件扩展名可用于页面。
  • A page.js file is required to make a route segment publicly accessible.
  • 需要一个 page.js 文件来使路由段可公开访问。
  • Pages are Server Components by default but can be set to a Client Component.
  • 默认情况下,页面是服务器组件,但可以设置为客户端组件。
  • Pages can fetch data. View the Data Fetching section for more information.
  • 页面可以获取数据。查看数据获取部分了解更多信息。

Layouts

布局

A layout is UI that is shared between multiple pages. On navigation, layouts preserve state, remain interactive, and do not re-render. Layouts can also be nested.

布局是在多个页面之间共享的 UI。在导航时,布局会保留状态、保持交互并且不会重新呈现。布局也可以嵌套。

You can define a layout by default exporting a React component from a layout.js file. The component should accept a children prop that will be populated with a child layout (if it exists) or a child page during rendering.

您可以默认从 layout.js 文件导出 React 组件来定义布局。该组件应该接受一个 children 道具,该道具将在渲染期间填充子布局(如果存在)或子页面。

image.png

app/dashboard/layout.tsx
export default function DashboardLayout({
  children, // will be a page or nested layout
}: {
  children: React.ReactNode;
}) {
  return (
    <section>
      {/* Include shared UI here e.g. a header or sidebar */}
      <nav></nav>
      {children}
    </section>
  );
}

Good to know:

很高兴知道:

  • The top-most layout is called the Root Layout. This required layout is shared across all pages in an application. Root layouts must contain html and body tags.
  • 最顶层的布局称为根布局。这个必需的布局在应用程序的所有页面之间共享。根布局必须包含 html 和 body 标签。
  • Any route segment can optionally define its own Layout. These layouts will be shared across all pages in that segment.
  • 任何路线段都可以选择定义自己的布局。这些布局将在该段的所有页面中共享。
  • Layouts in a route are nested by default. Each parent layout wraps child layouts below it using the React children prop.
  • 默认情况下,路由中的布局是嵌套的。每个父布局都使用 React children 属性将子布局包裹在其下方。
  • You can use Route Groups to opt specific route segments in and out of shared layouts.
  • 您可以使用路线组选择特定路线段进出共享布局。
  • Layouts are Server Components by default but can be set to a Client Component.
  • 默认情况下,布局是服务器组件,但可以设置为客户端组件。
  • Layouts can fetch data. View the Data Fetching section for more information.
  • 布局可以获取数据。查看数据获取部分了解更多信息。
  • Passing data between a parent layout and its children is not possible. However, you can fetch the same data in a route more than once, and React will automatically dedupe the requests without affecting performance.
  • 无法在父布局与其子布局之间传递数据。但是,您可以在一条路由中多次获取相同的数据,React 会自动对请求进行重复数据删除,而不会影响性能。
  • Layouts do not have access to the current route segment(s). To access route segments, you can use useSelectedLayoutSegment or useSelectedLayoutSegments in a Client Component.
  • 布局无权访问当前路线段。要访问路线段,您可以使用 useSelectedLayoutSegment 或 useSelectedLayoutSegments
    在客户端组件中。
  • .js, .jsx, or .tsx file extensions can be used for Layouts.
  • .js、.jsx 或 .tsx 文件扩展名可用于布局。
  • A layout.js and page.js file can be defined in the same folder. The layout will wrap the page.
  • layout.js 和 page.js 文件可以定义在同一个文件夹中。布局将包装页面。

Root Layout (Required)

根布局(必需)

The root layout is defined at the top level of the app directory and applies to all routes. This layout enables you to modify the initial HTML returned from the server.

根布局定义在应用程序目录的顶层,适用于所有路由。此布局使您能够修改从服务器返回的初始 HTML。

app/layout.tsx

export default function RootLayout({
  children,
}: {
  children: React.ReactNode,
}) {
  return (
    <html lang="en">
      <body>{children}</body>{" "}
    </html>
  );
}

Good to know:

很高兴知道:

  • The app directory must include a root layout.
  • 应用程序目录必须包含根布局。
  • The root layout must define <html> and <body> tags since Next.js does not automatically create them.
  • 根布局必须定义  和  标签,因为 Next.js 不会自动创建它们。
  • You can use the built-in SEO support to manage <head> HTML elements, for example, the <title> element.
  • 您可以使用内置的 SEO 支持来管理  HTML 元素,例如  元素。
  • You can use route groups to create multiple root layouts. See an example here.
  • 您可以使用路由组来创建多个根布局。请在此处查看示例。
  • The root layout is a Server Component by default and can not be set to a Client Component.
  • 默认情况下,根布局是一个服务器组件,不能设置为客户端组件。

Migrating from the pages directory: The root layout replaces the _app.js and _document.js files. View the migration guide.

从页面目录迁移:根布局替换了 _app.js 和 _document.js 文件。查看迁移指南。

Nesting Layouts

嵌套布局

Layouts defined inside a folder (e.g. app/dashboard/layout.js) apply to specific route segments (e.g. acme.com/dashboard) and render when those segments are active. By default, layouts in the file hierarchy are nested, which means they wrap child layouts via their children prop.

在文件夹内定义的布局(例如 app/dashboard/layout.js)适用于特定的路线段(例如 acme.com/dashboard)并在这些段处于活动状态时呈现。默认情况下,文件层次结构中的布局是嵌套的,这意味着它们通过 children 属性包装子布局。

image.png

app/dashboard/layout.tsx

export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode,
}) {
  return <section>{children}</section>;
}

If you were to combine the two layouts above, the root layout (app/layout.js) would wrap the dashboard layout (app/dashboard/layout.js), which would wrap route segments inside app/dashboard/*.

如果您要组合上面的两个布局,根布局 (app/layout.js) 将包装仪表板布局 (app/dashboard/layout.js),这会将路由段包装在 app/dashboard/* 内。

The two layouts would be nested as such:

这两个布局将嵌套如下:

image.png

You can use Route Groups to opt specific route segments in and out of shared layouts.

您可以使用路线组选择特定路线段进出共享布局。

Templates

模板

Templates are similar to layouts in that they wrap each child layout or page. Unlike layouts that persist across routes and maintain state, templates create a new instance for each of their children on navigation. This means that when a user navigates between routes that share a template, a new instance of the component is mounted, DOM elements are recreated, state is not preserved, and effects are re-synchronized.

模板类似于布局,因为它们包装每个子布局或页面。与跨路由持续存在并保持状态的布局不同,模板在导航时为它们的每个子元素创建一个新实例。这意味着当用户在共享模板的路由之间导航时,将安装组件的新实例,重新创建 DOM 元素,不保留状态,并重新同步效果。

There may be cases where you need those specific behaviors, and templates would be a more suitable option than layouts. For example:

在某些情况下,您可能需要那些特定的行为,而模板将是比布局更合适的选择。例如:

  • Enter/exit animations using CSS or animation libraries.
  • 使用 CSS 或动画库进入/退出动画。
  • Features that rely on useEffect (e.g logging page views) and useState (e.g a per-page feedback form).
  • 依赖于 useEffect(例如记录页面视图)和 useState(例如每页反馈表)的功能。
  • To change the default framework behavior. For example, Suspense Boundaries inside layouts only show the fallback the first time the Layout is loaded and not when switching pages. For templates, the fallback is shown on each navigation.
  • 更改默认框架行为。例如,布局中的 Suspense Boundaries 仅在第一次加载布局时显示后备,而不是在切换页面时显示。对于模板,后备显示在每个导航中。

Recommendation: We recommend using Layouts unless you have a specific reason to use Template.

建议:我们建议使用布局,除非您有使用模板的特定原因。

A template can be defined by exporting a default React component from a template.js file. The component should accept a children prop which will be nested segments.

可以通过从 template.js 文件导出默认的 React 组件来定义模板。该组件应该接受一个 children 道具,这将是嵌套的段。

image.png

app/template.tsx

export default function Template({ children }: { children: React.ReactNode }) {
  return <div>{children}</div>;
}

The rendered output of a route segment with a layout and a template will be as such:

具有布局和模板的路由段的渲染输出将如下所示:

Output

<Layout>
  {/* Note that the template is given a unique key. */}{" "}
  <Template key={routeParam}>{children}</Template>
</Layout>;

Modifying <head>

修改

In the app directory, you can modify the <head> HTML elements such as title and meta using the built-in SEO support.

在应用程序目录中,您可以使用内置的 SEO 支持修改  HTML 元素,例如标题和元数据。

Metadata can be defined by exporting a metadata object or generateMetadata function in a layout.js or page.js file.

可以通过在 layout.js 或 page.js 文件中导出元数据对象或 generateMetadata 函数来定义元数据。

app/page.tsx

export const metadata = { title: "Next.js" };
export default function Page() {
  return "...";
}

Good to know: You should not manually add <head> tags such as <title> and <meta> to root layouts. Instead, you should use the Metadata API which automatically handles advanced requirements such as streaming and de-duplicating <head> elements.

提示:您不应该手动添加  标签,例如  和  到根布局。相反,您应该使用元数据 API,它会自动处理高级要求,例如流式处理和去重  元素。

Learn more about available metadata options in the API reference.

在 API 参考中了解有关可用元数据选项的更多信息。

Linking and Navigating

链接和导航

The Next.js router uses server-centric routing with client-side navigation. It supports instant loading states and concurrent rendering. This means navigation maintains client-side state, avoids expensive re-renders, is interruptible, and doesn't cause race conditions.

Next.js 路由器使用以服务器为中心的路由和客户端导航。它支持即时加载状态和并发渲染

这意味着导航保持客户端状态,避免昂贵的重新渲染,是可中断的,并且不会导致竞争条件。

There are two ways to navigate between routes:

有两种方法可以在路线之间导航:

This page will go through how to use <Link>, useRouter(), and dive deeper into how navigation works.

本页将介绍如何使用 、useRouter(),并深入探讨导航的工作原理。

The <Link> Component

<Link> 组件

<Link> is a React component that extends the HTML <a> element to provide prefetching and client-side navigation between routes. It is the primary way to navigate between routes in Next.js.

<Link> 是一个 React 组件,它扩展了 HTML 元素以提供路由之间的预取和客户端导航。这是在 Next.js 中的路由之间导航的主要方式。

To use <Link>, import it from next/link, and pass a href prop to the component:

要使用 <Link>,请从 next/link 导入它,并将 href prop 传递给组件:

app/page.tsx

import Link from 'next/link';
export default function Page() {
  return <Link href="/dashboard">Dashboard</Link>;
}

There are optional props you can pass to <Link>. See the API reference for more information.

您可以将可选道具传递给 。有关详细信息,请参阅 API 参考。

Examples

例子

Linking to Dynamic Segments

链接到动态片段

When linking to dynamic segments, you can use template literals and interpolation to generate a list of links. For example, to generate a list of blog posts:

链接到动态段时,您可以使用模板文字和插值生成链接列表。例如,要生成博客文章列表:

app/blog/PostList.jsx

import Link from 'next/link';
export default function PostList({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>
          <Link href={`/blog/${post.slug}`}>{post.title}</Link>
        </li>
      ))}
    </ul>
  );
}

Checking Active Links

检查活动链接

You can use usePathname() to determine if a link is active. For example, to add a class to the active link, you can check if the current pathname matches the href of the link:

您可以使用 usePathname() 来确定链接是否处于活动状态。例如,要将一个类添加到活动链接,您可以检查当前路径名是否与链接的 href 匹配:

app/ui/Navigation.jsx

'use client';
import { usePathname } from 'next/navigation';
import { Link } from 'next/link';
export function Navigation({ navLinks }) {
  const pathname = usePathname();
  return (
    <>
      {navLinks.map((link) => {
        const isActive = pathname.startsWith(link.href);
        return (
          <Link
            className={isActive ? 'text-blue' : 'text-black'}
            href={link.href}
            key={link.name}
          >
            {link.name}
          </Link>
        );
      })}
    </>
  );
}

Scrolling to an id

滚动到一个 id

The default behavior of <Link> is to scroll to the top of the route segment that has changed. When there is an id defined in href, it will scroll to the specific id, similarly to a normal <a> tag.

<Link> 的默认行为是滚动到已更改的路线段的顶部。当 href 中定义了 id 时,它会滚动到特定的 id,类似于普通的 标签。

To prevent scrolling to the top of the route segment, set scroll={false} and pass the add a hashed id to href:

为了防止滚动到路由段的顶部,设置 scroll={false} 并将添加一个哈希 id 传递给 href:

sql

复制代码

<Link href="/#hashid" scroll={false}>  Scrolltospecific id.</Link>

The useRouter() Hook

useRouter() 钩子

The useRouter hook allows you to programmatically change routes inside Client Components.

useRouter 挂钩允许您以编程方式更改客户端组件内的路由。

To use useRouter, import it from next/navigation, and call the hook inside your Client Component:

要使用 useRouter,请从 next/navigation 导入它,并在您的客户端组件中调用钩子:

'use client';
import { useRouter } from 'next/navigation';
export default function Page() {
  const router = useRouter();
  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  );
}

The useRouter provides methods such as push(), refresh(), and more. See the API reference for more information.

useRouter 提供了 push()、refresh() 等方法。有关详细信息,请参阅 API 参考。

Recommendation: Use the <Link> component to navigate between routes unless you have a specific requirement for using useRouter.

建议:使用 <Link> 组件在路由之间导航,除非您有使用 useRouter 的特定要求。

How Navigation Works

导航的工作原理

  • A route transition is initiated using <Link> or calling router.push().
  • 使用  或调用 router.push() 启动路由转换。
  • The router updates the URL in the browser's address bar.
  • 路由器更新浏览器地址栏中的 URL。
  • The router avoids unnecessary work by re-using segments that haven't changed (e.g. shared layouts) from the client-side cache. This is also referred to as partial rendering.
  • 路由器通过重新使用客户端缓存中未更改的段(例如共享布局)来避免不必要的工作。这也称为部分渲染。
  • If the conditions of soft navigation are met, the router fetches the new segment from the cache rather than the server. If not, the router performs a hard navigation and fetches the Server Component payload from the server.
  • 如果满足软导航的条件,则路由器从缓存而不是服务器中获取新段。如果不是,路由器将执行硬导航并从服务器获取服务器组件有效负载。
  • If created, loading UI is shown from the server while the payload is being fetched.
  • 如果已创建,则会在获取有效负载时从服务器显示加载 UI。
  • The router uses the cached or fresh payload to render the new segments on the client.
  • 路由器使用缓存的或新的有效负载在客户端上呈现新的段。

Client-side Caching of Rendered Server Components

渲染服务器组件的客户端缓存

Good to know: This client-side cache is different from the server-side Next.js HTTP cache.

提示:此客户端缓存不同于服务器端 Next.js HTTP 缓存。

The new router has an in-memory client-side cache that stores the rendered result of Server Components (payload). The cache is split by route segments which allows invalidation at any level and ensures consistency across concurrent renders.

新路由器有一个内存中的客户端缓存,用于存储服务器组件(有效负载)的渲染结果。缓存按路由段拆分,允许在任何级别失效并确保并发渲染之间的一致性。

As users navigate around the app, the router will store the payload of previously fetched segments andprefetched segments in the cache.

当用户在应用程序中导航时,路由器会将先前获取的段和预取段的有效负载存储在缓存中。

This means, for certain cases, the router can re-use the cache instead of making a new request to the server. This improves performance by avoiding re-fetching data and re-rendering components unnecessarily.

这意味着,在某些情况下,路由器可以重新使用缓存而不是向服务器发出新请求。这通过避免不必要地重新获取数据和重新渲染组件来提高性能。

Invalidating the Cache

使缓存失效

Server Actions can be used to revalidate data on-demand by path (revalidatePath) or by cache tag (revalidateTag).

服务器操作可用于通过路径 (revalidatePath) 或缓存标记 (revalidateTag) 按需重新验证数据。


目录
相关文章
|
2月前
|
小程序 JavaScript 前端开发
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
764 1
|
3月前
|
监控 JavaScript 前端开发
深入理解 Nuxt.js 中的 app:error 钩子
【9月更文挑战第25天】在 Nuxt.js 中,`app:error` 钩子是一个强大的工具,用于处理应用程序中的各种错误。它可以在服务器端渲染或客户端运行时触发,帮助提升应用稳定性和用户体验。通过在 `nuxt.config.js` 中定义该钩子,开发者可以实现错误页面显示、错误日志记录及错误恢复等功能,确保应用在遇到问题时能妥善处理并恢复正常运行。
56 10
|
4月前
|
资源调度 JavaScript Linux
【Azure 应用服务】本地Node.js部署上云(Azure App Service for Linux)遇到的三个问题解决之道
【Azure 应用服务】本地Node.js部署上云(Azure App Service for Linux)遇到的三个问题解决之道
|
3月前
|
开发者 UED
深入理解 Nuxt.js 中的 app:error 钩子
【9月更文挑战第26天】在 Nuxt.js 中,钩子函数是在特定生命周期阶段执行代码的机制,`app:error` 钩子用于处理应用中的错误,包括服务器端和客户端渲染时出现的问题。它提供了一个集中处理错误的机制,提升了用户体验。当组件渲染过程中出现错误时,`app:error` 钩子会被触发,可以在 `nuxt.config.js` 文件中定义该钩子。通过分析错误对象 `err` 和上下文信息 `context`,开发者可以更好地处理各种错误情况。相比组件内的 `try/catch` 或浏览器原生错误处理,`app:error` 提供了更全局和有针对性的错误处理方式。
|
4月前
|
JavaScript 前端开发
【Azure Developer】在App Service上放置一个JS页面并引用msal.min.js成功获取AAD用户名示例
【Azure Developer】在App Service上放置一个JS页面并引用msal.min.js成功获取AAD用户名示例
|
4月前
|
JavaScript 前端开发 UED
揭秘Vue.js高效开发:Vue Router如何让单页面应用路由管理变得如此简单?
【8月更文挑战第30天】随着Web应用复杂性的增加,单页面应用(SPA)因出色的用户体验和高效的页面加载性能而备受青睐。Vue.js凭借简洁的语法和灵活的组件系统成为构建SPA的热门选择,其官方路由管理器Vue Router则简化了路由管理。本文通过实战示例介绍如何利用Vue Router实现高效的SPA路由管理,包括命名路由、动态路由及其核心优势。
51 0
|
4月前
|
JavaScript Windows
【Azure 应用服务】用App Service部署运行 Vue.js 编写的项目,应该怎么部署运行呢?
【Azure 应用服务】用App Service部署运行 Vue.js 编写的项目,应该怎么部署运行呢?
|
4月前
|
开发框架 JavaScript 前端开发
【Azure Developer】App Service + PubSub +JS 实现多人版黑客帝国文字流效果图
【Azure Developer】App Service + PubSub +JS 实现多人版黑客帝国文字流效果图
|
4月前
|
前端开发 JavaScript Linux
【Azure 应用服务】在Azure App Service for Linux环境中,部署的Django应用,出现加载css、js等静态资源文件失败
【Azure 应用服务】在Azure App Service for Linux环境中,部署的Django应用,出现加载css、js等静态资源文件失败
|
5月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的成人教育APP附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的成人教育APP附带文章源码部署视频讲解等
61 2

热门文章

最新文章