关于react.js:基于ResizeObserver实现一个自动计算宽高的react组件

48次阅读

共计 1803 个字符,预计需要花费 5 分钟才能阅读完成。

主动计算宽高的 react 组件

github 地址:https://github.com/niexq/reac… 欢送 Star

🏠 主页预览

📦 装置

  yarn add @oyyds/react-auto-sizer  # or npm i @oyyds/react-auto-sizer -S

🔨 应用

import AutoSizer from '@oyyds/react-auto-sizer';

const AutoSizeComponent = () => {
  return (
    <div>
      <AutoSizer>
        {({width, height}) => (
          <div
            style={{
              width,
              height,
            }}
          >
            内容区
          </div>
        )}
      </AutoSizer>
    </div>
  );
};

🧩 业务场景

当初大部分业务场景须要兼容大数据,例如 大数据表格,大数据树,大数据下拉框 等等,而所有的大数据组件都须要指定 宽高 ,理论业务界面大部分须要实时计算宽高,而 react-auto-sizer 就是来实现 主动计算宽高的使命

🧑‍💻 编码实现

期初预研 windows 上绑定 resize,但因 resize 会在窗体变动时,会有性能问题,局部极其像素状况下会呈现抖动;

ResizeObserver,接口能够监听到 Element 的内容区域或 SVGElement 的边界框扭转。内容区域则须要减去内边距 padding。— 摘自 MDN

ResizeObserver天选之子,应用 react hook useEffect,外围代码如下:


const updateState = useCallback((newWidth: number, newHeight: number, entry: ResizeObserverEntry) => {
      // 省略更新 state
      // 回调传入 width, height
      props.onResize({width: newWidth, height: newHeight}, entry);
    },
    [childParams, disableHeight, disableWidth, onResize],
  );

const observer = useMemo(() =>
      new ResizeObserver((entries: ResizeObserverEntry[]) => {for (const entry of entries) {
          const contentRect = entry.contentRect;
          const width = Math.trunc(contentRect?.width || 0);
          const height = Math.trunc(contentRect?.height || 0);
          updateState(width, height, entry);
        }
      }),
    [updateState],
  );
  
useEffect(() => {if (!_autoSizerRef?.current?.parentNode) {throw new Error('Not Found AutoSizer parentNode');
    }
    observer.observe(_autoSizerRef?.current?.parentNode as Element);
    return () => {observer.disconnect();
    };
  }, [observer]);

重点:

observer.observe(_autoSizerRef?.current?.parentNode as Element), 监听 父级 dom 节点

contentRect: ResizeObserverEntry返回一个DOMRectReadOnly 的只读属性contentRect,蕴含察看元素的新大小的对象,属性:

{
  "x": 0,
  "y": 0,
  "width": 300,
  "height": 200,
  "top": 0,
  "right": 300,
  "bottom": 200,
  "left": 0
}

contentRect 返回是 content box,也就是内容区域的尺寸(具体起因可参考张鑫旭大佬的 ResizeObserver 简介)

所以 contentRect.widthcontentRect.height就是咱们最终须要的宽高

🐳 灵感起源

react-virtualized-auto-sizer
ResizeObserver
检测 DOM 尺寸变动 JS API ResizeObserver

🐠 往期水文

不必递归生成有限层级的树

基于 qiankun 微前端实战部署

正文完
 0