You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React大数据表格滚动优化:解决卡顿与闪烁问题

基于React的大表格滚动性能优化问题

我正在开发一个基于React的表格,该表格包含大量单元格,滚动时出现性能问题。我已尝试仅渲染视口内可见单元格(类似react-window的实现),虽有改善但仍存在明显闪烁。

const Body = React.memo((props: BodyProps) => {
    const { columns, data, rowStart, rowEnd, colStart, colEnd, width, height } = props;

    const rows = [];
    for (let i = rowStart; i < rowEnd; i++) {
        rows.push(
            <Row
                columns={columns}
                data={data[i]}
                colStart={colStart}
                colEnd={colEnd}
                rowIndex={i}
                key={i}
             />
        );
    }

    return (
        <div
            className="body"
            style={{ width, height }}
        >
            {rows}
        </div>
    );
});

const Row = React.memo((props: RowProps) => {
    const { columns, data, colStart, colEnd, rowIndex } = props;

    const cells = [];
    for (let i = colStart; i < colEnd; i++) {
        const { key } = columns[i];
        cells.push(
            <Cell
                text={data[key]}
                colIndex={i}
                key={i}
            />
        );
    }

    return (
        <div
            className="row"
            style={{
                width: columns.length * tableColWidth,
                height: tableRowHeight,
                top: rowIndex * tableRowHeight
            }}
        >
            {cells}
        </div>
    );
});

性能分析发现耗时主要在Recalculating Styles,了解到布局抖动问题后,我改为在scroll事件中仅保存滚动位置,在requestAnimationFrame回调中处理,但无效果。

useLayoutEffect(() => {
    const callback = () => {
        const x = viewRef.current!.scrollLeft;
        const y = viewRef!.current!.scrollTop;
        scrollPositionRef.current = { x, y };
    }

    viewRef.current?.addEventListener("scroll", callback);
    return () => viewRef.current!.removeEventListener("scroll", callback);
}, []);

useLayoutEffect(() => {
    const animate = () => {
        const lastScrollPosition = scrollPositionRef.current;
        const { x, y } = lastScrollPosition;

        const newRowOffset = Math.floor(y / tableRowHeight);
        const newColOffset = Math.floor(x / tableColWidth);
        setOffsets([newRowOffset, newColOffset]);

        rafIdRef.current = requestAnimationFrame(animate);
    }

    rafIdRef.current = requestAnimationFrame(animate);
    return () => {
        if (rafIdRef.current) {
            cancelAnimationFrame(rafIdRef.current);
        }
    }
}, []);

请问是否能实现无卡顿闪烁、至少60FPS的渲染?若可以,我哪里出错了?若不行,原因是什么?我认为渲染数百个DOM元素不应如此复杂。


内容的提问来源于stack exchange,提问作者bzrr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:13:12