Next.js 学习笔记(六)——缓存

news2024/11/20 3:20:06

缓存

Next.js 可通过缓存渲染工作和数据请求来提高应用程序的性能并降低成本。本页将深入介绍 Next.js 缓存机制、可用于配置这些机制的 API 以及它们之间的交互方式。

需要知道:本页将帮助你了解 Next.js 的工作原理,但这并不是使用 Next.js 提高工作效率的必要知识。Next.js 的大部分缓存启发式方法都是由 API 使用情况决定的,默认情况下只需进行零配置或最少配置即可获得最佳性能。

概述

以下是不同缓存机制及其目的的高级概览:

机制是什么在哪里目的持续时间
请求记忆化函数返回值服务器在 React 组件树中重用数据每请求生命周期
数据缓存数据服务器跨用户请求和部署存储数据持久性(可重新验证)
全路由缓存HTML 和 RSC 有效负载服务器降低渲染成本并提高性能持久(可重新验证)
路由器缓存RSC 有效负载客户端减少导航时的服务器请求用户会话或基于时间的请求

默认情况下,Next.js 会尽可能多地缓存,以提高性能并降低成本。这意味着路由会静态渲染,数据请求也会缓存,除非你选择退出。下图显示了默认的缓存行为:在构建时静态渲染路由,以及首次访问静态路由。

在这里插入图片描述

缓存行为的变化取决于路由是静态渲染还是动态渲染,数据是缓存还是未缓存,以及请求是首次访问的一部分还是后续导航的一部分。根据使用情况,你可以为单个路由和数据请求配置缓存行为。

请求记忆化

React 扩展了 fetch API,可自动记忆具有相同 URL 和选项的请求。这意味着你可以在 React 组件树中的多个位置调用获取相同数据的函数,而只需执行一次。

在这里插入图片描述

例如,如果你需要在路由中使用相同的数据(例如:在布局、页面和多个组件中),你不必在树的顶端获取数据,然后在组件之间转发 props。相反,你可以在需要的组件中获取数据,而不必担心通过网络对相同数据进行多次请求会影响性能。

// app/example.tsx

async function getItem() {
  // fetch 函数会自动记忆结果
  const res = await fetch('https://.../item/1')
  return res.json()
}

// 这个函数被调用了两次,但仅执行了第一次
const item = await getItem() // cache MISS

// 第二次需要在路由中调用
const item = await getItem() // cache HIT

记忆请求是如何工作的?

在这里插入图片描述

  • 在渲染路由时,第一次调用特定请求时,其结果不会在内存中,而是缓存 MISS
  • 因此,函数将会被执行,从外部源获取数据,并将结果存储在内存中。
  • 在同一渲染传递中对请求的后续函数调用将是缓存 HIT,数据将从内存中返回,而不会执行函数。
  • 路由渲染和渲染过程完成后,记忆将被 “重置”,并且所有请求记忆条目将被清除。

需要知道

  • 请求记忆化是 React 的一项功能,而不是 Next.js 的一项功能。这里包含它是为了展示它是如何与其他缓存机制交互的。
  • 记忆化仅适用于 fetch 请求中的 GET 方法。
  • 记忆化仅适用于 React 组件树,也就是说:
    • 它适用于 generateMetadatagenerateStaticParams、Layouts、Pages 和其他服务器组件中的获取请求。
    • 它不适用于路由处理程序中的 fetch 请求,因为它们不是 React 组件树的一部分。
  • 对于不适合 fetch 的情况(例如:某些数据库客户端、CMS 客户端或 GraphQL 客户端),你可以使用 React catch 函数来记忆函数。

持续时间

缓存的持续时间与服务器请求的持续时间相同,直到 React 组件树完成渲染。

重新验证

由于记忆化不会在跨服务器请求中共享,而且只应用在渲染过程中,因此无需重新验证。

选择退出

要在 fetch 请求中选择退出记忆化,你可以向请求传递 AbortController signal

// app/example.js

const { signal } = new AbortController()
fetch(url, { signal })

数据缓存

Next.js 有一个内置的数据缓存,可以在传入的服务器请求部署中持久化数据提取的结果。之所以能做到这一点,是因为 Next.js 扩展了本地 fetch API,以允许服务器上的每个请求设置自己的持久缓存语义。

需要知道:在浏览器中,fetchcache 选项表示请求将如何与浏览器的 HTTP 缓存交互,而在 Next.js 中,cache 选项表示服务器端请求将如何与服务器的数据缓存交互。

默认情况下,使用 fetch 的数据请求会被缓存。你可以使用 fetchcachenext.revalidate 选项来配置缓存行为。

数据缓存的工作原理

在这里插入图片描述

  • 在渲染过程中首次调用 fetch 请求时,Next.js 会检查数据缓存是否有缓存响应。
  • 如果找到缓存响应,会立即返回并记忆。
  • 如果未找到缓存响应,则会向数据源发出请求,将结果存储在数据缓存中并被记忆。
  • 对于未缓存的数据(例如,{ cache: 'no-store' }),结果总是从数据源获取,并被记忆。
  • 无论数据是缓存的还是未缓存的,请求都会被记忆,以避免在 React 渲染过程中对相同数据进行重复请求。

数据缓存与请求记忆化的区别

虽然这两种缓存机制都能通过重复使用缓存数据来提高性能,但数据缓存是跨传入请求和部署的持久性缓存,而记忆化则只在请求的生命周期内有效。

有了记忆化,我们就能减少同一渲染过程中从渲染服务器到数据缓存服务器(如:CDN 或 Edge 网络)或数据源(如:数据库或 CMS(内容管理系统))之间必须跨越网络边界的重复请求数量。有了数据缓存,我们就能减少对原始数据源的请求次数。

持续时间

除非你重新验证或选择退出,否则数据缓存会在接收请求和部署过程中持续存在。

重新验证

缓存数据可通过以下两种方式重新验证:

  • 基于时间的重新验证: 在一定时间后,当有新请求时,重新验证数据。这对于变化不频繁、新鲜度要求不高的数据非常有用。
  • 按需重新验证: 根据事件(如:表单提交)重新验证数据。按需重新验证可以使用基于标签或路径的方法,一次性重新验证数据组。当你想确保尽快显示最新数据时(例如:当无头 CMS(内容管理系统)的内容更新时),这种方法非常有用。
基于时间的重新验证

要按时间间隔重新验证数据,可以使用 fetchnext.revalidate 选项来设置资源的缓存时间(以秒为单位)。

// 最多每小时验证一次
fetch('https://...', { next: { revalidate: 3600 } })

或者,你也可以使用路由段配置选项来配置段中的所有 fetch 请求,或者用于无法使用 fetch 功能的情况。

基于时间的重新验证的工作原理

在这里插入图片描述

  • 首次调用带有 revalidatefetch 请求时,数据将从外部数据源获取并存储在数据缓存中。
  • 在指定时限(如:60 秒)内调用的任何请求都将返回缓存数据。
  • 时限过后,下一次请求仍将返回缓存数据(现在是陈旧数据)。
    • Next.js 将在后台触发数据的重新验证。
    • 一旦数据获取成功,Next.js 就会使用新数据更新数据缓存。
    • 如果后台重新验证失败,之前的数据将保持不变。

这与 stale-while-revalidate 行为类似。

按需重新验证

数据可按路径(revalidatePath)或缓存标签(revalidateTag)进行按需重新验证。

按需重新验证的工作原理

在这里插入图片描述

  • 首次调用 fetch 请求时,数据将从外部数据源获取并存储在数据缓存中。
  • 当触发按需重新验证时,缓存中的相应缓存条目将被清除。
    • 这与基于时间的重新验证不同,后者会将陈旧数据保留在缓存中,直到获取到新数据。
  • 下一次发出请求时,将再次出现缓存 MISS,数据将从外部数据源获取并存储到数据缓存中。

选择退出

对于单个数据获取,可以通过将 cache 选项设置为 no-store来选择退出缓存。这意味着只要调用 fetch,就会获取数据。

// 为单个 `fetch` 请求选择退出缓存
fetch(`https://...`, { cache: 'no-store' })

或者,你也可以使用路由段配置选项来选择退出特定路由段的缓存。这将影响路由段中的所有数据请求,包括第三方库。

// 选择不对路由段中的所有数据请求进行缓存
export const dynamic = 'force-dynamic'

Vercel 数据缓存

如果你的 Next.js 应用程序部署到了 Vercel,我们建议你阅读 Vercel 数据缓存文档,以便更好地了解 Vercel 的具体功能。

全路由缓存

相关术语:

你可能会看到自动静态优化静态网站生成静态渲染等术语被交替使用,用来指在构建时渲染和缓存应用程序路由的过程。

Next.js 会在构建时自动渲染和缓存路由。这是一种优化,可让你为缓存的路由提供服务,而不是每次请求都在服务器上渲染,从而加快页面加载速度。

要了解完整路由缓存的工作原理,不妨先看看 React 是如何处理渲染的,以及 Next.js 是如何缓存结果的:

1. React 在服务器上的渲染

在服务器上,Next.js 使用 React 的 API 来协调渲染。渲染工作被分成若干小块:按单个路由段和悬念边界划分。

每个分块分两步进行渲染:

  1. React 会将服务器组件渲染为一种特殊的数据格式,并针对流式传输进行了优化,这种格式称为 React 服务器组件有效载荷(React Server Component Payload)。
  2. Next.js 使用 React 服务器组件有效载荷和客户端组件 JavaScript 指令在服务器上渲染 HTML。

这意味着我们不必等待所有内容都渲染完毕后再缓存或发送响应。相反,我们可以在工作完成后以流式方式发送响应。

什么是 React 服务器组件有效载荷?

React Server Component Payload 是渲染的 React 服务器组件树的紧凑二进制表示。它被客户端上的 React 用来更新浏览器的 DOM。React 服务器组件有效载荷包含:

  • ​ 服务器组件的渲染结果
  • ​ 客户端组件应渲染位置的占位符及其 JavaScript 文件的引用
  • ​ 从服务器组件传递到客户端组件的任何 props

要了解更多信息,请参阅服务器组件文档。

2. Next.js 在服务器上的缓存(全路由缓存)

在这里插入图片描述

Next.js 的默认行为是在服务器上缓存路由的渲染结果(React 服务器组件有效负载和 HTML)。这适用于在构建时或重新验证时静态渲染的路由。

3. React 在客户端上的水合和调和

在客户端请求时:

  1. HTML 用于立即显示客户端和服务器组件的快速非交互式初始预览。
  2. React 服务器组件有效载荷用于调节客户端和渲染的服务器组件树,并更新 DOM。
  3. JavaScript 指令用于水合客户端组件并使应用程序具有交互性。

4. Next.js 在客户端上的缓存(路由器缓存)

React 服务器组件有效载荷存储在客户端的路由器缓存中,这是一个独立的内存缓存,按单个路由段分割。路由器缓存用于存储以前访问过的路由并预取未来的路由,从而改善导航体验。

5. 后续导航

在后续导航或预取过程中,Next.js 会检查 React 服务器组件有效载荷是否存储在路由器缓存中。如果是,它将跳过向服务器发送新请求。

如果路由段不在缓存中,Next.js 将从服务器获取 React 服务器组件有效载荷,并在客户端填充路由器缓存。

静态和动态渲染

路由在构建时是否被缓存取决于它是静态渲染还是动态渲染。静态路由默认为缓存,而动态路由在请求时渲染,不进行缓存。

此图显示了静态路由和动态路由在缓存和未缓存数据时的区别:

在这里插入图片描述

了解更多静态和动态渲染。

持续时间

默认情况下,全路由缓存是持久的。这意味着渲染输出会在用户请求时缓存。

失效

有两种方法可以使完整路由缓存失效:

  • 重新验证数据: 通过在服务器上重新渲染组件并缓存新的渲染输出,重新验证数据缓存将反过来使路由器缓存失效。
  • 重新部署: 与在不同部署中持续存在的数据缓存的区别是,完整路由缓存会在新部署时被清除。

选择退出

你可以选择不使用全路由缓存,或者换句话说,通过以下方式为每个传入请求动态渲染组件:

  • 使用动态函数: 这将从全路由缓存中选择路由,并在请求时动态渲染。数据缓存仍可使用。
  • 使用 dynamic = 'force-dynamic'revalidate = 0 路由段配置选项: 这将跳过全路由缓存和数据缓存。这意味着在每次向服务器发送请求时,都会对组件进行渲染并获取数据。路由器缓存仍然适用,因为它是客户端缓存。
  • 选择退出数据缓存: 如果一个路由有一个未缓存的 fetch 请求,这将使该路由退出全路由缓存。每次传入请求时,都会获取特定 fetch 请求的数据。其他未选择退出缓存的 fetch 请求仍将在数据缓存中缓存。这样就可以实现缓存与非缓存数据的混合。

路由缓存

相关术语:

你可能会看到路由器缓存被称为客户端缓存(Client-side Cache)预取缓存(Prefetch Cache)

  • 预取缓存指的是预取的路由段
  • 客户端缓存指的是整个路由器缓存,包括访问过的路由段和预取的路由段。

这种缓存特别适用于 Next.js 和服务器组件,与浏览器的 bfcache 不同,但结果类似。

Next.js 有一个内存客户端缓存,用于在用户会话期间存储按单个路由段分割的 React 服务器组件有效载荷。这就是所谓的路由器缓存(Router Cache)。

路由缓存的工作原理

在这里插入图片描述

当用户在路由之间导航时,Next.js 会缓存已访问的路线段,并预取用户可能导航到的路由(基于视口中的 <Link> 组件)。

这将改善用户的导航体验:

  • 由于已缓存访问过的路由,因此可即时向前/向后导航;由于预取和部分渲染,因此可快速导航到新路由。
  • 导航之间无需重新加载整个页面,React 状态和浏览器状态都会保留。

路由器缓存与全路由缓存之间的区别:

路由器缓存会在用户会话期间将 React 服务器组件有效载荷临时存储在浏览器中,而全路由缓存会在多个用户请求期间将 React 服务器组件有效载荷和 HTML 持久存储在服务器上。

全路由缓存只缓存静态渲染的路由,而路由器缓存则同时适用于静态和动态渲染的路由。

持续时间

缓存存储在浏览器的临时内存中。路由器缓存的持续时间由两个因素决定:

  • 会话:缓存在浏览过程中持续存在。不过,它会在页面刷新时被清除。
  • 自动失效期:单个网段的缓存会在特定时间后自动失效。持续时间取决于路径是静态渲染还是动态渲染:
    • 动态渲染:30 秒
    • 静态渲染:5 分钟

虽然页面刷新会清除所有缓存区段,但自动失效期只影响上次访问或创建时的单个区段。

通过为动态渲染的路由添加 prefetch={true} 或调用 router.prefetch,可以选择缓存 5 分钟。

失效

有两种方法可以使路由器缓存失效:

  • 服务器操作中:
    • 使用(revalidatePath)按路径或(revalidateTag)按缓存标签按需失效数据
    • 使用 cookies.setcookies.delete 可使路由器缓存失效,以防止使用 cookies 的路由(例如:身份验证)变得过时
  • 调用 router.refresh 会使路由器缓存失效,并就当前路由向服务器发出新请求

退出

无法退出路由器缓存。

你可以通过将 <Link> 组件的 prefetch prop 设置为 false 来退出预取。不过,这仍会暂时存储路由段 30 秒,以便在嵌套路由段之间进行即时导航,例如:标签栏或前后导航。访问过的路由仍会被缓存。

缓存互动

在配置不同的缓存机制时,了解它们之间的相互作用非常重要:

数据缓存和全路由缓存

  • 重新启用或退出数据缓存将使完整路由缓存失效,因为渲染输出取决于数据。
  • 失效或退出全路由缓存不会影响数据缓存。你可以动态渲染既有缓存数据又有未缓存数据的路由。当大部分页面使用缓存数据,但有一些组件依赖于需要在请求时获取的数据时,这种方法就非常有用。你可以动态渲染,而不必担心重新获取所有数据会影响性能。

数据缓存和客户端路由器缓存

  • 路由处理程序中的数据缓存重新失效不会立即使路由器缓存失效,因为路由处理程序并未与特定路由绑定。这意味着路由器缓存将继续提供之前的有效负载,直到强制刷新或自动失效期结束。
  • 要立即使数据缓存和路由器缓存失效,可以在服务器操作中使用 revalidatePathrevalidateTag

APIs

下表概述了不同 Next.js API 对缓存的影响:

API路由器缓存全路由缓存数据缓存React 缓存
<Link prefetch>缓存
router.prefetch缓存
router.refresh重新验证
fetch缓存缓存
fetch options.cache缓存 或 选择退出
fetch options.next.revalidate重新验证重新验证
fetch options.next.tags缓存缓存
revalidateTag重新验证(服务器操作)重新验证重新验证
revalidatePath重新验证(服务器操作)重新验证重新验证
const revalidate重新验证 或 选择退出重新验证 或 选择退出
const dynamic缓存 或 选择退出缓存 或 选择退出
cookies重新验证(服务器操作)选择退出
headers, searchParams选择退出
generateStaticParams缓存
React.cache缓存
unstable_cache

<Link>

默认情况下,<Link> 组件会自动从全路由缓存中预取路由,并将 React 服务器组件有效载荷添加到路由器缓存中。

要禁用预取,可以将 prefetch prop 设置为 false。但这不会永久跳过缓存,当用户访问路由时,路由段仍会在客户端缓存。

了解有关 <Link> 组件的更多信息。

router.prefetch

useRouter 钩子的 prefetch 选项可用于手动预取路由。这会将 React 服务器组件有效载荷添加到路由器缓存中。

请参阅 useRouter 钩子 API 参考。

router.refresh

useRouter 钩子的 refresh 选项可用于手动刷新路由。这将彻底清除路由器缓存,并就当前路由向服务器发出新请求。refresh 不会影响数据或完整路由缓存。

渲染结果将在客户端进行调节,同时保留 React 状态和浏览器状态。

请参见 useRouter 钩子 API 参考。

fetch

fetch 返回的数据会自动缓存在数据缓存中。

// 默认缓存。`force-cache` 是默认选项,可以省略。
fetch(`https://...`, { cache: 'force-cache' })

有关更多选项,请参阅 fetch API 参考。

fetch options.cache

通过将 cache 选项设置为 no-store,你可以选择不对单个 fetch 请求进行数据缓存:

// 选择退出缓存
fetch(`https://...`, { cache: 'no-store' })

由于渲染输出取决于数据,因此使用 cache: 'no-store' 也会跳过使用 fetch 请求的路由的全路由缓存。也就是说,路由将在每次请求时动态渲染,但同一路由中仍可以有其他缓存数据请求。

有关更多选项,请参阅 fetch API 参考。

fetch options.next.revalidate

你可以使用 fetchnext.revalidate 选项来设置单个 fetch 请求的重新验证周期(以秒为单位)。这将重新验证数据缓存,进而重新验证全路由缓存。服务器将获取新数据并重新渲染组件。

// 最多 1 小时后重新验证
fetch(`https://...`, { next: { revalidate: 3600 } })

有关更多选项,请参阅 fetch API 参考。

fetch options.next.tagsrevalidateTag

Next.js 有一个缓存标签系统,用于细粒度数据缓存和重新验证。

  1. 使用 fetchunstable_cache 时,你可以选择用一个或多个标签来标记缓存条目。
  2. 然后,可以调用 revalidateTag 来清除与该标签相关的缓存条目。

例如,你可以在获取数据时设置一个标签:

// 带有标签缓存数据
fetch(`https://...`, { next: { tags: ['a', 'b', 'c'] } })

然后,调用带有标签的 revalidateTag 来清除缓存条目:

// 重新验证带有特定标记的条目
revalidateTag('a')

你可以在两个地方使用 revalidateTag,具体取决于你要实现的目标:

  1. 路由处理程序 - 响应第三方事件(例如:webhook)时重新验证数据。这不会立即使路由器缓存失效,因为路由器处理程序并不与特定路由绑定。
  2. 服务器操作 - 在用户操作(例如:表单提交)后重新验证数据。这将使相关路由的路由器缓存失效。

revalidatePath

revalidatePath 允许你在一次操作中手动重新验证数据并重新渲染特定路径下的路由段。调用 revalidatePath 方法可重新验证数据缓存,进而使全路由缓存失效。

revalidatePath('/')

你可以在两个地方使用 revalidatePath,具体取决于你要实现的目标:

  1. 路由处理程序 - 响应第三方事件(例如:webhook)时重新验证数据。
  2. 服务器操作 - 在用户交互(例如:提交表单、点击按钮)后重新验证数据。

更多信息,请参阅 revalidatePath API 参考。

revalidatePathrouter.refresh 的比较:

调用 router.refresh 会清除路由器缓存,并在服务器上重新渲染路由段,而不会使数据缓存或全路由缓存失效。

两者的区别在于,revalidatePath清除数据缓存和全路由缓存,而 router.refresh() 不会更改数据缓存和全路由缓存,因为它是客户端 API。

动态函数

页面中的动态函数(例如:cookieheaderssearchParams prop)依赖于运行时传入的请求信息。使用它们会将路由从全路由缓存中选择出来,换句话说,路由将被动态渲染。

cookie

在服务器操作中使用 cookies.setcookies.delete 会使路由缓存失效,以防止使用 cookies 的路由变得陈旧(例如:反映身份验证的更改)。

请参阅 cookies API 参考。

段配置选项

路由段配置选项可用于覆盖路由段默认值,或在无法使用 fetch API 时使用(例如:数据库客户端或第三方库)。

以下路由段配置选项将退出数据缓存和全路由缓存:

  • const dynamic = 'force-dynamic
  • const revalidate = 0

有关更多选项,请参阅路由分段配置文档。

generateStaticParams

对于动态段(例如:app/blog/[slug]/page.js),generateStaticParams 提供的路径会在构建时缓存在全路由缓存中。在请求时,Next.js 还会缓存首次访问时在构建时未知的路径。

你可以在路由段中使用 export const dynamicParams = false 选项,在请求时禁用缓存。使用此配置选项时,只有 generateStaticParams 提供的路径才会得到服务,其他路由将是 404 或匹配(在捕获全局路由的情况下)。

请参阅 generateStaticParams API 参考。

React cache 函数

通过 React cache 函数,你可以对函数的返回值进行记忆,从而可以多次调用同一个函数,而只执行一次。

由于 fetch 请求会自动记忆,因此你无需将其封装在 React cache 中。不过,在不适合使用 fetch API 的用例中,你可以使用 cache 来手动对数据请求进行记忆。例如,某些数据库客户端、CMS 客户端或 GraphQL 客户端。

// utils/get-item.ts

import { cache } from 'react'
import db from '@/lib/db'
 
export const getItem = cache(async (id: string) => {
  const item = await db.item.findUnique({ id })
  return item
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1375402.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1 月 21 日,三件事儿,线上不见不散丨社区活动

1 月 21 日&#xff0c;三件事儿&#xff0c;线上不见不散&#xff1a; RTE 开发者社区&#xff0c;三位联合主理人正式亮相&#xff0c;分享对于行业、社区与开发者人才发展的思考&#xff1b;「实时互动行业人才洞察2024」正式发布&#xff0c;关于行业、人才与生态的分析与…

【Python学习】Python学习13-日期和时间

目录 【Python学习】Python学习13-日期和时间 前言通过time 获取时间戳时间元组获取当前时间&#xff0c;格式化时间格式化时间转换python中时间日期格式化符号获取日历Time 模块日历&#xff08;Calendar&#xff09;模块其他模块参考 文章所属专区 Python学习 前言 本章节主…

Macos下修改Python版本

MacOS下修改Python版本 安装 查看本机已安装的Python版本&#xff1a;where python3 ~ where python3 /usr/bin/python3 /usr/local/bin/python3 /Library/Frameworks/Python.framework/Versions/3.12/bin/python3如果没有你想要的版本&#xff0c;去python官网下载安装包。…

【金猿案例展】黑龙江省粮食质量安全监测和技术中心——荣联助力黑龙江粮食仓储智能化升级...

‍ 荣联科技集团案例 本项目案例由荣联科技集团投递并参与“数据猿年度金猿策划活动——2023大数据产业年度创新服务企业榜单/奖项”评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 近年来&#xff0c;国家粮食和物资储备信息化工作取得了长足发展&#xff0c;但与新时…

C++ Primer 6.1 函数基础

函数的形参列表 int func(int v,int v2) {int v,v2;//&#xff01;错误 } 函数返回类型 不能是数组和函数&#xff08;两者都不接受对拷&#xff09;&#xff0c;但可以是指针 局部对象 形参和函数体内部的变量称为局部变量&#xff0c;仅在函数内部可见&#xff0c;隐藏外部…

行为型设计模式——策略模式

策略模式 策略模式非常简单&#xff0c;只需要将策略或者某个算法定义成一个类&#xff0c;然后传给需要使用的对象即可。**定义&#xff1a;**该模式定义了一系列算法&#xff0c;并将每个算法封装起来&#xff0c;使它们可以相互替换&#xff0c;且算法的变化不会影响使用算…

【c++】list迭代器失效问题

目录 一、list iterator的使用 二、list的迭代器失效 一、list iterator的使用 对于list的迭代器的用法&#xff0c;可以将它看做一个指针&#xff08;实际要更加复杂&#xff09;来使用&#xff0c;该指针指向list中的一个节点。 【注意】 (1)begin和end为正向迭代器&#x…

【C语言刷题每日一题#牛客网HJ73】——计算日期到天数转换(给定日期,计算是该年的第几天)

目录 问题描述 思路分析 数据结构构建部分 计算部分 代码实现 结果测试 此问题解决方法不唯一&#xff0c;这里介绍的是一种使用数组和循环实现的简单办法 问题描述 思路分析 问题的要求是输入一个日期&#xff0c;计算这是当年的第几天——要解决这个问题&#xff0c;逻…

记录汇川:H5U与Fctory IO测试8

主程序&#xff1a; 子程序&#xff1a; IO映射 子程序&#xff1a; 出料程序 子程序&#xff1a; 重量程序 子程序&#xff1a; 自动程序 Fctory IO配置&#xff1a; HMI配置 实际动作如下&#xff1a; Fctory IO测试8

SPI接口协议

SPI接口协议 SPI(Serial Peripheral Interface)是由Motorola公司定义的接口协议标准&#xff0c;串行外设接口(SPI)是微控制器和外围IC&#xff08;如传感器、 ADC、 DAC、移位寄存器、 SRAM等&#xff09;之间使用最广泛的接口之一。SPI是一种同步、全双工、主从式接口&#x…

智慧农庄电商小程序(商城系统)

文章目录 项目简介商城功能项目结构技术选型后端使用的技术前端使用的技术 程序体验 项目简介 基于当前流行技术组合的前后端分离商城系统&#xff1a; SpringBoot2JpaMybatisPlusSpringSecurityjwtredisVue的前后端分离的商城系统&#xff0c; 包含商城、拼团、砍价、商户管理…

redis stream restTemplate消息监听队列框架搭建

整体思路 1. pom增加redis依赖&#xff1b; 2. 消息监听器&#xff0c;实现StreamListener接口&#xff0c;处理消息到达逻辑&#xff1b; 3. 将消息订阅bean及监听器注册到配置中&#xff1b; 1. pom <?xml version"1.0" encoding"UTF-8"?> <…

【MySQL】锁机制

文章目录 一、表级锁和行级锁二、排他锁和共享锁三、InnoDB行级锁行级锁间隙锁意向共享锁和意向排他锁 四、InnoDB表级锁五、死锁六、锁的优化建议 一、表级锁和行级锁 表级锁&#xff1a; 对整张表加锁。开销小&#xff0c;加锁快&#xff0c;不会出现死锁&#xff1b;锁粒度…

c++学习笔记-STL案例-机房预约系统1-准备工作

前言 准备工作包括&#xff1a;需求分析、项目创建、主菜单实现、退出功能实现 目录 1 机房预约系统需求 1.1 简单介绍 1.2 身份介绍 1.3 机房介绍 1.4 申请介绍 1.5 系统具体要求 1.6 预约系统-主界面思维导图 2 创建项目 2.1 创建项目 2.2 添加文件 ​编辑 3 创建…

VTK开发调试环境下载(VTK开发环境一步到位直接开发,无需自己配置编译 VS2017+Qt5.12.10+VTK)

一、无与伦比的优势 直接下载代码就可以调试的VTK代码仓库。 二、资源制作原理 这个资源根据VTK源码 编译出动态库文件 pdb lib dll 文件&#xff08; x64 debug &#xff09; 并将这两者同时放在一个代码仓库里&#xff0c;下载就能用。 三、使用方法&#xff08;vtk-so…

【hyperledger-fabric】部署Java应用远程访问智能合约

简介 首先是根据b站的视频 hyperledger-fabric【3】在 java 应用中访问合约 以及hyperledger-fabric【5】Java应用和私有数据&#xff0c;本文章主要讲述的是视频中我遇到的问题&#xff0c;以及相关知识点的总结。 遇到的问题 问题1&#xff1a;git clone下载下来的代码发现…

Unity Meta Quest 一体机开发(十三):【手势追踪】自定义交互事件 EventWrapper

文章目录 &#x1f4d5;教程说明&#x1f4d5;交互事件概述&#x1f4d5;自定义交互逻辑⭐方法一&#xff1a;Inspector 面板赋值⭐方法二&#xff1a;纯代码处理 此教程相关的详细教案&#xff0c;文档&#xff0c;思维导图和工程文件会放入 Spatial XR 社区。这是一个高质量…

XCTF:CatCatCat[WriteUP]

从题目中下载到一张图片和一个txt文件 编码的开头是&#xff1a;U2FsdGVkX1所以是rabbit加密 尝试使用密钥&#xff1a;91 密码不对&#xff0c;无法解密所以从图片下手 使用010Editor搜索图片文本内容 尝试搜索password、flag等敏感字体 直接拿到rabbit解密需要的密钥是&am…

【AI视野·今日Sound 声学论文速览 第四十四期】Tue, 9 Jan 2024

AI视野今日CS.Sound 声学论文速览 Tue, 9 Jan 2024 Totally 27 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers DJCM: A Deep Joint Cascade Model for Singing Voice Separation and Vocal Pitch Estimation Authors Haojie Wei, Xueke Cao, Wenbo Xu…

移动光缆使用规定

移动光缆使用的规定&#xff1a; 1.1在移动光缆的施工过程中&#xff0c;其弯曲半径应该是移动光缆外径的15倍&#xff0c;并且不能小于20倍。 1.2在进行移动光缆敷设时&#xff0c;需要确保施加的拉力不超过移动光缆所允许的张力的80%。移动光缆的最大张力允许达到100%的限制…