主动计算宽高的 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微前端实战部署