react-virtualized-auto-sizer插件一般用来和react-window,配合使用,react-virtualized-auto-sizer负责获取,父元素的宽度和高度,传入到List中,但实战时,往往有些列表用到了隐藏显示, 比方说disabled:none;当使用disabled为none时,react-virtualized-auto-sizer会移除子元素;当返回时,元素会重新渲染,滚动条也会滚到顶部;
备注:如果是'visibility: hidden;'子元素会保留,但其会仍然占用宽度和高度,实战中很多场景不适用,这里不展开讨论;
项目中依赖
bash
"react-virtualized-auto-sizer": "^1.0.20",
"react-window": "^1.8.9",
日常使用
typescript
<AutoSizer>
{({ height, width }: {height: number, width: number}) => (
<List
height={height}
itemCount={curMonitorList.length}
itemSize={48}
width={width}>
{renderOrgItem}
</List>
)
}
</AutoSizer>
目前未找到方案,所以重新写了一个自定义组件完成AutoSizer要办的事
typescript
import { useEffect, useState, useRef } from "react";
interface PropsType{
children: any
}
export default function AzAutoSizer({children}: PropsType) {
const curRef = useRef<HTMLDivElement>(null)
const [curWidthHeight, setCurWidthHeight] = useState({
height: 0,
width: 0,
});
const handleClick = () => {
if (curRef.current) {
const parentNode: any = curRef.current.parentNode;
const height = parentNode.offsetHeight;
const width = parentNode.offsetWidth;
curWidthHeight.height = height || 0;
curWidthHeight.width = width || 0;
setCurWidthHeight({...curWidthHeight});
}
};
useEffect(() => {
handleClick();
const handleResize = () => {
/* 如果示父或祖先disabled: none时,其父高度宽度都为0;
if (!curRef.current) { return; }
const parentNode: any = curRef.current.parentNode;
const height = parentNode.offsetHeight
const width = parentNode.offsetWidth;
// 表示父或祖先disabled: none;
if (height === 0 && width === 0) {
return;
}
*/
handleClick();
};
/* 监听窗口改变 */
window.addEventListener('resize', handleResize);
/* 是否进入可视化-1.创建观察函数 */
const observer = new IntersectionObserver(([{ isIntersecting }]) => {
if (isIntersecting) {
if (!curRef.current) { return; }
if (curWidthHeight.height !== 0 && curWidthHeight.width !== 0) {
/* 如果这段代码放出来的话要解开resize那边的代码判断,才能满足父或祖先元素disabled:none时组件宽高被重置为none
*/
// observer.unobserve(curRef.current);
} else {
handleClick();
}
}
});
/* 是否进入可视化-1.监听当前元素 */
curRef.current && observer.observe(curRef.current);
return () => {
/* 卸载窗口监听 */
window.removeEventListener('resize', handleResize);
/* 卸载可视化监听 */
if (curRef.current) {
observer.unobserve(curRef.current);
}
};
}, []);
return <div ref={curRef} style={{width: `${curWidthHeight.width}px`, height: `${ curWidthHeight.height}px`}}>
{children({height: curWidthHeight.height, width: curWidthHeight.width})}
</div>
}
使用方法
typescript
<AzAutoSizer >
{({ height, width }: {height: number, width: number}) => (
<List
height={height}
itemCount={curMonitorList.length}
itemSize={48}
width={width}>
{renderOrgItem}
</List>
)
}
</AzAutoSizer>