gpt4 book ai didi

reactjs - 在浏览器有机会绘制之前,React 如何正确测量 useLayoutEffect Hook 中的 DOM 元素?

转载 作者:行者123 更新时间:2023-12-02 21:24:33 25 4
gpt4 key购买 nike

在官方 React 文档中,对于 useLayoutEffect ,其中提到:

The signature is identical to useEffect, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint.

此外,在 useLayoutEffect 中,我们能够在浏览器实际重新绘制之前读取更新的尺寸。

react 是如何做到这一点的?

最佳答案

所以@Marko 是对的。

浏览器渲染周期分为几个阶段,相关的阶段是:

  1. 样式 - 将 HTML 与 CSS 合并
  2. 布局 - 计算所有元素的大小和位置
  3. 油漆

Mozilla docs

useLayoutEffect 在布局之后、绘制之前运行

要实现这一点,您需要做的(或 React 所做的)就是在 DOM 树中添加或更改元素后同步运行 useLayoutEffect 函数。

除非您释放线程,否则浏览器无法运行绘画阶段。

如果您向浏览器询问元素的大小,它会同步运行布局阶段来给您答案。

这是一个片段和一个 sandbox演示这个想法:

const conatiner = document.getElementById("container");

function busyWait() {
const array = new Array(100000).fill(Math.random());
let sum = 0;
array.forEach((val, index) => {
const item = array.find((val, i) => i === index);
sum = sum + item;
});
return sum;
}

function addElement() {
const newElement = document.createElement("p");
newElement.innerText =
"this is a paragraph, browser need to measure it to know its size";

if (conatiner) {
conatiner.appendChild(newElement);
console.log(
"layout phase element size",
JSON.stringify(newElement.getBoundingClientRect())
);
const sum = busyWait();
console.log(sum);

setTimeout(() => {
console.log(
"after paint element size",
JSON.stringify(newElement.getBoundingClientRect())
);
}, 10);
}
}

setTimeout(addElement, 100);
<div>
we are going to test layout / replaint stages
<div id="container" style="width: 200px;"></div>
</div>

  • 我添加一个新元素
  • 询问其尺寸
  • 记录它
  • 然后忙等待(不将线程释放给浏览器)=> 您可以在日志中看到正确的大小,但在屏幕上看不到该元素

关于reactjs - 在浏览器有机会绘制之前,React 如何正确测量 useLayoutEffect Hook 中的 DOM 元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60769022/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com