【问题标题】:How to detect overflow in a nested div (React)?如何检测嵌套 div (React) 中的溢出?
【发布时间】:2021-04-29 04:42:55
【问题描述】:

我想创建一个 div,它在 div 的底部显示模糊(当存在溢出时)。问题是div包含props.children,里面还包含其他组件/html标签。

我尝试使用 ref (React.useRef),但在子渲染之前就设置了 ref。我尝试将 useEffect 与 ref 一起使用,但当我使用例如 element.current.scrollbarHeight 时,我仍然得到 0。

如何检查渲染的 div(带有子元素)是否溢出? (我使用的是功能组件)

<div> {props.children} </div> 

为了生成模糊,我使用样式组件。

【问题讨论】:

  • 您能否分享所有代码以提供帮助?
  • 亲爱的@KhaledAhmed,实际上
    ... 是我唯一需要帮助的事情。我在 styled-components 中添加的唯一内容是 div 的高度,为 280 像素。我只是想知道 props.children 是否会导致溢出。我不知道 props.children 会包含什么,它几乎总是有不同的长度和内容。
  • 我不确定如果没有每个子节点都提供专门的回调,是否有可能知道是否完全渲染了任意子节点。因此,通过在github.com/marcj/css-element-queries 中的useEffect 中设置一些沿 ResizeSensor 行的东西,观察元素的大小变化可能会更好
  • 您可以创建一个包含 2 个 div 的嵌套。 codesandbox.io/s/react-content-resized-detection-3f3gr 。不客气。当您处理onContentResized 事件时,您需要检查scrollHeightoffsetHeight。让我知道你的进展情况,如果有帮助,我会给你一个真正的答案。
  • 我进行了一些更改以更好地反映使用情况,现在在onContentResized 中传递hasOverflow 参数。也许这会有所帮助。 codesandbox.io/s/react-content-resized-detection-3f3gr

标签: javascript reactjs typescript styled-components


【解决方案1】:

如果没有每个子节点都提供专门的回调,就不可能知道任意子节点是否被完全渲染。因此,观察元素的大小变化可能会更好。

我们可以在这里使用ResizeObserver 来发挥我们的优势。

如果我们创建一对嵌套的 div:

<div class="fixed_size_overflow_auto">
    <div>
        {children}
    </div>
</div>

使外部 div 具有固定的尺寸,我们可以在内部 div 上监听调整大小。当我们检测到这些调整大小时,我们可以通过比较它的offsetHeight 和它的scrollHeight 来计算外部 div 是否溢出。

这是一个想法,包含在一个可以使用styled-components 设置样式的组件中:

const DetectContentResizeElement: FC<{
  className?: string;
  onContentResized?: (v: { hasOverflow: boolean }) => void;
}> = ({ children, onContentResized, className }) => {

  const contentRef = useRef<HTMLDivElement>(null);
  const outerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!contentRef.current || !outerRef.current) {
      return;
    }

    const obs = new ResizeObserver(() => {
      const hasOverflow =
        (outerRef.current?.offsetHeight ?? 0) <
        (contentRef.current?.offsetHeight ?? 0);
      onContentResized?.({ hasOverflow });
    });

    obs.observe(contentRef.current);
    return () => obs.disconnect();
  }, [onContentResized]);

  return (
    <div className={className} ref={outerRef}>
      <div ref={contentRef}>{children}</div>
    </div>
  );
};

您可以通过使用 styled-components 对其进行“子类化”来固定该组件的大小:

const FixedHeight = styled(DetectContentResizeElement)`
  height: 200px;
  width: 200px;
  border: solid 1px black;
  overflow: auto;
`;

所以现在您可以使用此容器并获取告诉您何时溢出的事件:

  <FixedHeight
    onContentResized={({ hasOverflow }) =>
      console.log(`resized. hasOverflow: ${hasOverflow}`)
    }
  >
    <SomeChildElement />
  </FixedHeight>

codesandbox project 中查看它的实际效果(使用resize-observer-polyfill ponyfill 以获得最佳兼容性)

【讨论】:

    猜你喜欢
    相关资源
    最近更新 更多
    热门标签