学习实现虚拟列表的过程中,让类名为holder的元素不占据高度的情况下,发现页面在往下滚动的过程中出现滚动条抖动的问题,并且是反复抽搐,为什么会出现这样的情况
export default function VirtualList() {
const [position, setPosition] = useState({ start: 0, end: 0 });
const [data, setData] = useState([]);
const listBoxRef = useRef();
const contentRef = useRef();
const scrollInfo = useRef({
itemHeight: 60,
bufferCount: 8,
renderCount: 0
});
useEffect(() => {
const { itemHeight, bufferCount } = scrollInfo.current;
const { height } = listBoxRef.current.getBoundingClientRect();
const renderCount = Math.ceil(height / itemHeight) + bufferCount;
const dataList = new Array(10000).fill(0).map((_, index) => index + 1);
scrollInfo.current = { ...scrollInfo.current, renderCount };
setData(dataList);
setPosition({ start: 0, end: renderCount });
}, []);
const handleScroll = () => {
const { itemHeight, renderCount } = scrollInfo.current;
const scrollTop = listBoxRef.current.scrollTop;
console.log('scrollTop', scrollTop);
const start = Math.floor(scrollTop / itemHeight);
const end = start + renderCount;
// contentRef.current.style.transform = `translate3d(0, ${scrollTop}px, 0)`;
if (start !== position.start || end !== position.end) {
setPosition({ start, end });
}
};
console.log(position);
const { itemHeight } = scrollInfo.current;
return (
<div className="list-box" ref={listBoxRef} onScroll={handleScroll}>
<div
className="holder"
style={{ height: `${itemHeight * data.length}px` }}
></div>
<div className="content-area" ref={contentRef}>
{data.slice(position.start, position.end).map((item) => (
<div key={item} className="item">
{item}
</div>
))}
</div>
</div>
);
}
.item {
list-style: none;
background-color: #fc4838;
padding: 10px 20px;
color: #fff;
height: 50px;
line-height: 50px;
box-sizing: border-box;
margin-bottom: 10px;
margin-left: 24px;
margin-right: 24px;
font-weight: bold;
border-radius: 10px;
}
.list-box {
position: fixed;
left: 0;
right: 0;
top: 20px;
bottom: 0;
overflow: scroll;
}
.holder {
position: absolute;
top: 0;
left: 0;
right: 0;
}
浏览器滚动锚点导致,要么你每次滚动后重设
scrollTop
,要么css取消滚动锚点:overflow-anchor: none