Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions packages/components/hooks/useVirtualScroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const requestAnimationFrame =
const useVirtualScroll = (container: MutableRefObject<HTMLElement>, params: UseVirtualScrollParams) => {
const { data, scroll } = params;

const isUpdating = useRef(false);
const dataRef = useRef(data);
const containerHeight = useRef(0);

Expand Down Expand Up @@ -70,6 +71,8 @@ const useVirtualScroll = (container: MutableRefObject<HTMLElement>, params: UseV
};

const updateVisibleData = (trScrollTopHeightList: number[], scrollTop: number) => {
if (isUpdating.current) return;

let currentIndex = -1;
// 获取当前滚动到哪一个元素(大数据场景不建议使用 forEach 一类函数迭代)
for (let i = 0, len = trScrollTopHeightList.length; i < len; i++) {
Expand Down Expand Up @@ -117,13 +120,26 @@ const useVirtualScroll = (container: MutableRefObject<HTMLElement>, params: UseV
}

if (startAndEndIndex.join() !== [startIndex, endIndex].join() && startIndex >= 0) {
isUpdating.current = true;

const tmpVisibleData = fixedStartData.concat(data.slice(startIndex, endIndex)).concat(fixedEndData);
setVisibleData(tmpVisibleData);
const lastScrollTop = trScrollTopHeightList[startIndex - 1];
const top = lastScrollTop > 0 ? lastScrollTop : 0;

const topOffset = trScrollTopHeightList[startIndex - 1] ?? 0;
const stickyHeight = trScrollTopHeightList[Math.min(startIndex, fixedStart) - 1] || 0;
setTranslateY(top - stickyHeight);
setStartAndEndIndex([startIndex, endIndex]);
setTranslateY(topOffset - stickyHeight); // 先计当前帧的位移
setStartAndEndIndex([startIndex, endIndex]); // 再更新索引,确保数值稳定

const targetScrollTop = scrollTop;
setTimeout(() => {
const currentScrollTop = container.current?.scrollTop;
const scrollTopDiff = Math.abs(currentScrollTop - targetScrollTop);
if (scrollTopDiff > 0) {
// eslint-disable-next-line no-param-reassign
container.current.scrollTop = targetScrollTop;
Comment on lines +133 to +139
Copy link

Copilot AI Oct 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable targetScrollTop is assigned directly from scrollTop parameter without modification. This intermediate variable adds no value and can be removed - use scrollTop directly in the setTimeout callback.

Suggested change
const targetScrollTop = scrollTop;
setTimeout(() => {
const currentScrollTop = container.current?.scrollTop;
const scrollTopDiff = Math.abs(currentScrollTop - targetScrollTop);
if (scrollTopDiff > 0) {
// eslint-disable-next-line no-param-reassign
container.current.scrollTop = targetScrollTop;
setTimeout(() => {
const currentScrollTop = container.current?.scrollTop;
const scrollTopDiff = Math.abs(currentScrollTop - scrollTop);
if (scrollTopDiff > 0) {
// eslint-disable-next-line no-param-reassign
container.current.scrollTop = scrollTop;

Copilot uses AI. Check for mistakes.
}
isUpdating.current = false;
}, 0);
}
};

Expand Down Expand Up @@ -242,7 +258,7 @@ const useVirtualScroll = (container: MutableRefObject<HTMLElement>, params: UseV
trScrollTopHeightList.current = scrollTopHeightList;
clearTimeout(timer);
}
}, 1);
}, 0);
},
// eslint-disable-next-line
[container, data, tScroll, isVirtualScroll, startAndEndIndex, trHeightList],
Expand Down
2 changes: 1 addition & 1 deletion packages/components/table/TBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export default function TBody(props: TableBodyProps) {

const [global, t] = useLocaleReceiver('table');

const { skipSpansMap } = useRowspanAndColspan(data, columns, rowKey, props.rowspanAndColspan);
const { skipSpansMap } = useRowspanAndColspan(renderData, columns, rowKey, props.rowspanAndColspan);
const isSkipSnapsMapNotFinish = Boolean(props.rowspanAndColspan && !skipSpansMap.size);

const { tableFullRowClasses, tableBaseClass } = allTableClasses;
Expand Down
7 changes: 4 additions & 3 deletions packages/components/table/hooks/useRowspanAndColspan.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { useEffect, useState } from 'react';
import { useState } from 'react';
import { get } from 'lodash-es';
import log from '@tdesign/common-js/log/index';
import { BaseTableCellParams, BaseTableCol, TableRowData, TableRowspanAndColspanFunc } from '../type';
import useIsomorphicLayoutEffect from '../../hooks/useLayoutEffect';
import type { BaseTableCellParams, BaseTableCol, TableRowData, TableRowspanAndColspanFunc } from '../type';

export interface SkipSpansValue {
colspan?: number;
Expand Down Expand Up @@ -80,7 +81,7 @@ export default function useRowspanAndColspan(
return map;
};

useEffect(() => {
useIsomorphicLayoutEffect(() => {
if (!rowspanAndColspan) return;
skipSpansMap.clear();
const result = getSkipSpansMap(data, columns, rowspanAndColspan);
Expand Down
Loading