React Academy · 课时

用于动画前测量的 useLayoutEffect

使用 useLayoutEffect 在动画开始前测量元素尺寸,避免布局跳动。

第 3 / 4 课13 个步骤

用于动画前测量的 useLayoutEffect 是 CoddyKit 上的免费 React Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。

闪现问题

有时,元素在首次渲染时会明显跳动或闪烁,之后才稳定到正确位置。通常,这是因为您在浏览器已经绘制元素后才测量或重新定位它。

用户会在一帧中看到错误的位置,随后看到突然的修正,这看起来就像出了问题。

为什么 useEffect 会导致闪现

useEffect 会在浏览器绘制之后运行。因此,如果您在 useEffect 中读取测量值并更新 DOM,用户已经看到了尚未校正的那一帧,然后您的更改才会生效。

对于必须对用户不可见的视觉定位来说,绘制后的时序已经太晚了。

useLayoutEffect 在绘制前执行

useLayoutEffect 会在 React 修改 DOM 后、浏览器绘制前同步运行。您在其中进行的任何 DOM 读取或写入,都会在用户看到第一帧之前完成。

因此,对于必须立即显示为正确状态的测量和定位,它是合适的工具。

测量初始位置

在 useLayoutEffect 中,您可以使用 ref.current.getBoundingClientRect() 读取元素布局,在开始动画前获取它的位置和尺寸。

由于这会在绘制前运行,您可以同时完成测量并应用起始变换,而不会出现任何可见闪现。

FLIP 技术

FLIP 代表 First(初始)、Last(最终)、Invert(反转)和 Play(播放)。您先记录元素的初始位置,让它移动到最终位置;然后应用变换进行反转,使它在视觉上回到初始位置;最后移除变换,让它播放到最终位置。

这样,即使实际布局已经瞬间跳变,您仍然只使用开销较低的 transform 来为布局变化添加动画。

useLayoutEffect 中的 getBoundingClientRect

关键的读取操作发生在 useLayoutEffect 中:在更改前获取初始矩形,在更改后获取最终矩形,然后计算差值。在绘制前完成这些操作,可以确保反转变换已就位后再显示任何内容。

两个矩形之间的差异可以为您提供用于反转的精确平移量和缩放比例。

同步应用变换

您可以在 useLayoutEffect 中同步设置反转变换,然后在下一帧将其移除,让元素动画到自然位置。通常,您会使用 requestAnimationFrame 触发播放步骤。

由于反转变换是在绘制前应用的,用户永远不会看到元素处于未经处理的最终位置。

SSR 警告

服务器上没有 DOM,因此 React 会记录一条警告,指出 useLayoutEffect 在服务器渲染期间不起作用。布局副作用只有在浏览器中才有意义。

这条警告表示,在没有可供测量的内容时,该副作用无法运行。

兼容 SSR 的替代方案

如果组件必须在服务器上运行,请将 useEffect 与 requestAnimationFrame 结合使用,在下一次绘制前完成测量;或者仅在浏览器中有条件地使用 useLayoutEffect。

这样可以避免警告,同时为非关键动画提供接近绘制前的时序。

展开手风琴示例

高度动画是一个典型案例:在 useLayoutEffect 中测量折叠和展开后的高度,然后在明确的像素值之间添加动画,使过渡保持平滑。

由于 auto 高度无法添加动画,先测量实际高度就可以让您过渡到一个具体数值。

何时使用 useLayoutEffect

大多数情况下,请默认使用 useEffect。只有在您需要读取布局,并且必须在绘制前修改 DOM 以避免可见闪现时,才使用 useLayoutEffect。

过度使用它可能会损害性能,因为它会阻塞绘制,直到自身完成。

快速检查

请检验您对副作用时序的理解。

回顾

您了解了闪现问题源于绘制后才进行测量,了解了 useLayoutEffect 会在绘制前运行,也了解了 FLIP 技术如何使用开销较低的变换为布局变化添加动画。

您还看到了 SSR 警告,以及由 useEffect 和 requestAnimationFrame 组成的后备方案。

免费开始

用 AI 导师学习 React — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
88
课程
324

常见问题解答

「用于动画前测量的 useLayoutEffect」课时是免费的吗?

是的 — 「用于动画前测量的 useLayoutEffect」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。

「用于动画前测量的 useLayoutEffect」这节课中我会学到什么?

使用 useLayoutEffect 在动画开始前测量元素尺寸,避免布局跳动。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 React Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「用于动画前测量的 useLayoutEffect」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 React Academy 课中编写并运行代码吗?

能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. React 状态变化中的 CSS 过渡
  2. 使用 React 实现 CSS 关键帧动画
  3. 用于动画前测量的 useLayoutEffect
  4. 无需库实现进入和退出动画
← 返回 React Academy