Skip to content

Commit 3456029

Browse files
committed
fix(Table): dragSort failure when affix header is not mounted
1 parent 9c914d6 commit 3456029

4 files changed

Lines changed: 77 additions & 25 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { useCallback, useRef } from 'react';
2+
3+
function useDomRefMount<T extends HTMLElement = HTMLElement>(ref: React.MutableRefObject<T | null>) {
4+
const callbacks = useRef<Array<(node: T) => void>>([]);
5+
const unmountCallbacks = useRef<Array<() => void>>([]);
6+
7+
const onMount = useCallback(
8+
(nodeOrCallback: T | ((node: T) => void)) => {
9+
// 如果传入的是函数,则注册回调
10+
if (typeof nodeOrCallback === 'function') {
11+
callbacks.current.push(nodeOrCallback);
12+
return;
13+
}
14+
15+
// 否则是 ref 挂载
16+
const node = nodeOrCallback as T;
17+
const prevNode = ref?.current;
18+
19+
// 更新 ref
20+
if (ref) {
21+
// eslint-disable-next-line no-param-reassign
22+
ref.current = node;
23+
}
24+
25+
// 如果是新挂载(从 null 变为有值),触发所有挂载回调
26+
if (node && !prevNode) {
27+
callbacks.current.forEach((callback) => {
28+
callback(node);
29+
});
30+
}
31+
32+
// 如果是卸载(从有值变为 null),触发所有卸载回调
33+
if (!node && prevNode) {
34+
unmountCallbacks.current.forEach((callback) => {
35+
callback();
36+
});
37+
}
38+
39+
return node;
40+
},
41+
[], // eslint-disable-line react-hooks/exhaustive-deps
42+
);
43+
44+
const onUnmount = useCallback((callback: () => void) => {
45+
unmountCallbacks.current.push(callback);
46+
}, []);
47+
48+
const clearCallbacks = useCallback(() => {
49+
callbacks.current = [];
50+
unmountCallbacks.current = [];
51+
}, []);
52+
53+
return {
54+
onMount,
55+
onUnmount,
56+
clearCallbacks,
57+
};
58+
}
59+
60+
export default useDomRefMount;

packages/components/table/BaseTable.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ import React, {
77
useRef,
88
useState,
99
} from 'react';
10+
1011
import classNames from 'classnames';
1112
import { pick } from 'lodash-es';
1213

1314
import log from '@tdesign/common-js/log/index';
1415
import { getIEVersion } from '@tdesign/common-js/utils/helper';
1516
import Affix, { type AffixRef } from '../affix';
1617
import useDefaultProps from '../hooks/useDefaultProps';
18+
import useDomRefMount from '../hooks/useDomRefMount';
1719
import useElementLazyRender from '../hooks/useElementLazyRender';
1820
import useVirtualScroll from '../hooks/useVirtualScroll';
1921
import Loading from '../loading';
@@ -125,6 +127,8 @@ const BaseTable = forwardRef<BaseTableRef, BaseTableProps>((originalProps, ref)
125127
footerBottomAffixRef,
126128
});
127129

130+
const { onMount: onAffixHeaderMount } = useDomRefMount(affixHeaderRef);
131+
128132
const { dataSource, innerPagination, isPaginateData, renderPagination } = usePagination(props, tableContentRef);
129133

130134
// 列宽拖拽逻辑
@@ -269,7 +273,7 @@ const BaseTable = forwardRef<BaseTableRef, BaseTableProps>((originalProps, ref)
269273
const scrollColumnIntoView = (colKey: string) => {
270274
if (!tableContentRef.current) return;
271275
const thDom = tableContentRef.current.querySelector(`th[data-colkey="${colKey}"]`);
272-
const fixedThDom = tableContentRef.current.querySelectorAll('th.t-table__cell--fixed-left');
276+
const fixedThDom = tableContentRef.current.querySelectorAll(`th.${classPrefix}-table__cell--fixed-left`);
273277
let totalWidth = 0;
274278
for (let i = 0, len = fixedThDom.length; i < len; i++) {
275279
totalWidth += fixedThDom[i].getBoundingClientRect().width;
@@ -286,6 +290,7 @@ const BaseTable = forwardRef<BaseTableRef, BaseTableProps>((originalProps, ref)
286290
tableHtmlElement: tableElmRef.current,
287291
tableContentElement: tableContentRef.current,
288292
affixHeaderElement: affixHeaderRef.current,
293+
onAffixHeaderMount,
289294
refreshTable,
290295
scrollToElement: virtualConfig.scrollToElement,
291296
scrollColumnIntoView,
@@ -380,7 +385,7 @@ const BaseTable = forwardRef<BaseTableRef, BaseTableProps>((originalProps, ref)
380385
};
381386
const affixedHeader = Boolean((headerAffixedTop || virtualConfig.isVirtualScroll) && tableWidth) && (
382387
<div
383-
ref={affixHeaderRef}
388+
ref={onAffixHeaderMount}
384389
style={{ width: `${tableWidth}px`, opacity: headerOpacity }}
385390
className={classNames([
386391
'scrollbar',
@@ -495,7 +500,6 @@ const BaseTable = forwardRef<BaseTableRef, BaseTableProps>((originalProps, ref)
495500
tableContentRef,
496501
tableWidth,
497502
isWidthOverflow,
498-
allTableClasses,
499503
rowKey,
500504
scroll: props.scroll,
501505
cellEmptyContent: props.cellEmptyContent,

packages/components/table/TBody.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
import React, { type CSSProperties, type MutableRefObject, type ReactNode, useMemo } from 'react';
33
import classNames from 'classnames';
44
import { camelCase, get, pick } from 'lodash-es';
5+
56
import { useLocaleReceiver } from '../locale/LocalReceiver';
6-
import { TableClassName } from './hooks/useClassName';
7+
import useClassName from './hooks/useClassName';
78
import useRowspanAndColspan from './hooks/useRowspanAndColspan';
89
import TR, { ROW_LISTENERS, TABLE_PROPS, type TrProps } from './TR';
910

@@ -25,7 +26,6 @@ export interface TableBodyProps extends BaseTableProps {
2526
isWidthOverflow?: boolean;
2627
virtualConfig: VirtualScrollConfig;
2728
pagination?: PaginationProps;
28-
allTableClasses?: TableClassName;
2929
handleRowMounted?: (params: RowMountedParams) => void;
3030
}
3131

@@ -74,7 +74,7 @@ const trProperties = [
7474

7575
export default function TBody(props: TableBodyProps) {
7676
// 如果不是变量复用,没必要对每一个参数进行解构(解构过程需要单独的内存空间存储临时变量)
77-
const { data, columns, rowKey, firstFullRow, lastFullRow, virtualConfig, allTableClasses } = props;
77+
const { data, columns, rowKey, firstFullRow, lastFullRow, virtualConfig } = props;
7878

7979
const { isVirtualScroll } = virtualConfig;
8080
const renderData = isVirtualScroll ? virtualConfig.visibleData : data;
@@ -84,7 +84,7 @@ export default function TBody(props: TableBodyProps) {
8484
const { skipSpansMap } = useRowspanAndColspan(renderData, columns, rowKey, props.rowspanAndColspan);
8585
const isSkipSnapsMapNotFinish = Boolean(props.rowspanAndColspan && !skipSpansMap.size);
8686

87-
const { tableFullRowClasses, tableBaseClass } = allTableClasses;
87+
const { tableFullRowClasses, tableBaseClass } = useClassName();
8888
const tbodyClasses = useMemo(() => [tableBaseClass.body], [tableBaseClass.body]);
8989
const hasFullRowConfig = useMemo(() => firstFullRow || lastFullRow, [firstFullRow, lastFullRow]);
9090

packages/components/table/hooks/useDragSort.ts

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -419,26 +419,14 @@ function useDragSort(props: TdEnhancedTableProps, options: DragSortOptions) {
419419

420420
// 注册拖拽事件
421421
useEffect(() => {
422-
if (!primaryTableRef || !primaryTableRef.current) return;
423-
registerRowDragEvent(primaryTableRef.current?.tableElement);
424-
registerColDragEvent(primaryTableRef.current?.tableHtmlElement);
425-
/** 待表头节点准备完成后 */
426-
const timer = setTimeout(() => {
427-
if (primaryTableRef.current?.affixHeaderElement) {
428-
registerColDragEvent(primaryTableRef.current.affixHeaderElement);
429-
}
430-
clearTimeout(timer);
422+
if (!primaryTableRef.current) return;
423+
registerRowDragEvent(primaryTableRef.current.tableElement);
424+
registerColDragEvent(primaryTableRef.current.tableHtmlElement);
425+
primaryTableRef.current.onAffixHeaderMount((el: HTMLDivElement) => {
426+
registerColDragEvent(el);
431427
});
432-
return () => {
433-
clearTimeout(timer);
434-
dragRowInstance.current?.destroy();
435-
dragRowInstance.current = null;
436-
dragColInstance.current?.destroy();
437-
dragColInstance.current = null;
438-
unlockScrollContainer();
439-
};
440428
// eslint-disable-next-line react-hooks/exhaustive-deps
441-
}, [primaryTableRef, columns, dragSort, innerPagination]);
429+
}, [columns, dragSort, innerPagination]);
442430

443431
return {
444432
isRowDraggable,

0 commit comments

Comments
 (0)