在第一页加载时反应不准确地计算 div 的高度

Posted

技术标签:

【中文标题】在第一页加载时反应不准确地计算 div 的高度【英文标题】:React inaccurately calculating the height of a div on first page load 【发布时间】:2021-07-20 09:00:41 【问题描述】:

我正在寻找一种可靠的策略来计算其中包含许多孩子的父母的身高,无论孩子是图像、视频还是字体等。(想想投资组合内容)

可以在此处找到该问题的一个简单示例:

https://codesandbox.io/s/wrong-height-tkvcm?file=/src/useHeight.js:347-545


图像加载速度很慢,因此计算函数会过早触发。并且由此产生的高度计算完全关闭。

我尝试过的事情

计算所有图像的比例,明确设置图像高度。这行得通,但是我仍然有视频、字体、慢速 API 也需要加载。所以这个策略感觉很坑爹。

调整大小观察者。也无法可靠地等待内容加载。性能昂贵。还有这个issue。

React setState/useEffect/array 依赖项。让我走得很远,但最终还是失败了,因为很难知道哪个状态会最后触发以更新高度计算。

我尝试了 React 并发模式来尝试在计算开始之前预加载内容。对于非 API 的情况,这似乎有点过头了。我只需要担心本地图像和资产。

  React.useEffect(() => 
    updateHeight();
    window.addEventListener("resize", updateHeight);
    return () => 
      window.removeEventListener("resize", updateHeight);
    ;
  , [updateHeight]);

我确实认为使用 React 预加载内容是最好的方法,但我很想知道是否有其他人尝试解决在内部包含大量内容的大型容器上计算尺寸的问题?

更复杂的例子: https://codesandbox.io/s/stupefied-wilson-qzb1i?file=/src/components/CaseWrapper/index.js:756-836

【问题讨论】:

【参考方案1】:

大小差异可能是由于您使用的自定义字体所致。刷新页面时,您会注意到字体加载后的文本移动。

尝试删除base.css中的所有@font-face,问题就会消失。

或者,您可以在计算高度之前等待document.fonts.ready 回调。

React.useEffect(() => 
  document.fonts.ready.then(function () 
    console.log('Fonts currently being used on the page are now loaded.');
    // Calculate height now
  );  
, []);

【讨论】:

感谢 Sohaib,绝对是管理布局抖动的有用方法,无论哪种方式我都会实现。我希望找到一个更简单的解决方案,可以预测加载的各种资产,而不仅仅是字体。还有更多 React-y。对于图像和视频,也许有类似的解决方案。 (我已经在使用 padding-bottom hack 来防止图像抛出布局)【参考方案2】:

    要确保所有图像都已加载,您可以在该 html 元素上使用 onLoad 事件。

    handleLoad 完成后会将状态“已加载”设置为 true

    然后您可以将'loaded' 状态传递给useHeight 并确保它在完成加载后计算元素

// App.js
...


return() (
  const [loaded, setLoaded] = useState(false);
  const height = useHeight(elementDOM, loaded); // 3.

  // 2.
  const handleLoad = () => 
    setLoaded(true);
  ;
  ...
    <div ref=elementDOM className="box" onLoad=handleLoad> // 1.
    ..
    ..
    </div>
  ...
);
...
// useHeight.js
...
function useHeight(elementRef, isLoaded) 
  const updateHeight = useCallback(() => 
    if (isLoaded && elementRef && elementRef.current) 
      const  height  = elementRef.current.getBoundingClientRect();
      setHeight(height);
    
  , [isLoaded, elementRef]);

  ...
  return height;
  ...

...

Forked sandbox

【讨论】:

以上是关于在第一页加载时反应不准确地计算 div 的高度的主要内容,如果未能解决你的问题,请参考以下文章

反应:使div的宽度等于高度。高度计算不正确

覆盖在第一页加载时奇怪可见的 jQuery UI Datepicker div。

Vue子组件在第一页加载时不显示动态数据

滚动加载数据

如何使DIV的高度固定,当超出固定高度时,出现自动滚动条

在第一页加载时从 createApi RTK 访问 localStorage