Skip to content

Commit

Permalink
fix(table): render times improvement; rowspanAndColspan (#2514)
Browse files Browse the repository at this point in the history
* fix(table): render times improvement; rowspanAndColspan

* fix(table): ref

* test: update snapshots
  • Loading branch information
chaishi authored Sep 17, 2023
1 parent 5f7c313 commit 495ddd0
Show file tree
Hide file tree
Showing 7 changed files with 318 additions and 278 deletions.
23 changes: 13 additions & 10 deletions src/table/BaseTable.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useRef, useMemo, useImperativeHandle, forwardRef, useEffect, useState, WheelEvent } from 'react';
import pick from 'lodash/pick';
import classNames from 'classnames';
import TBody, { extendTableProps } from './TBody';
import TBody, { extendTableProps, TableBodyProps } from './TBody';
import { Affix } from '../affix';
import { ROW_LISTENERS } from './TR';
import THead from './THead';
Expand Down Expand Up @@ -49,8 +49,10 @@ const BaseTable = forwardRef<BaseTableRef, BaseTableProps>((props, ref) => {
const tableElmRef = useRef<HTMLTableElement>();
const bottomContentRef = useRef<HTMLDivElement>();
const [tableFootHeight, setTableFootHeight] = useState(0);
const allTableClasses = useClassName();

const { classPrefix, virtualScrollClasses, tableLayoutClasses, tableBaseClass, tableColFixedClasses } =
useClassName();
allTableClasses;
// 表格基础样式类
const { tableClasses, sizeClassNames, tableContentStyles, tableElementStyles } = useStyle(props);
const { isMultipleHeader, spansAndLeafNodes, thList } = useTableHeader({ columns: props.columns });
Expand Down Expand Up @@ -422,7 +424,7 @@ const BaseTable = forwardRef<BaseTableRef, BaseTableProps>((props, ref) => {
return affixedFooter;
};

const tableBodyProps = {
const tableBodyProps: TableBodyProps = {
classPrefix,
ellipsisOverlayClassName: props.size !== 'medium' ? sizeClassNames[props.size] : '',
rowAndColFixedPosition,
Expand All @@ -431,10 +433,11 @@ const BaseTable = forwardRef<BaseTableRef, BaseTableProps>((props, ref) => {
virtualConfig,
handleRowMounted: virtualConfig.handleRowMounted,
columns: spansAndLeafNodes?.leafColumns || columns,
tableElm: tableRef.current,
tableContentElm: tableContentRef.current,
tableWidth: tableWidth.current,
tableRef,
tableContentRef,
tableWidth,
isWidthOverflow,
allTableClasses,
rowKey: props.rowKey || 'id',
scroll: props.scroll,
cellEmptyContent: props.cellEmptyContent,
Expand Down Expand Up @@ -483,15 +486,15 @@ const BaseTable = forwardRef<BaseTableRef, BaseTableProps>((props, ref) => {
),
// eslint-disable-next-line
[
tableBodyProps.classPrefix,
allTableClasses,
tableBodyProps.ellipsisOverlayClassName,
tableBodyProps.rowAndColFixedPosition,
tableBodyProps.showColumnShadow,
tableBodyProps.data,
tableBodyProps.columns,
tableBodyProps.tableElm,
tableBodyProps.tableContentElm,
tableBodyProps.tableWidth,
tableRef,
tableContentRef,
tableWidth,
isWidthOverflow,
props.rowKey,
props.rowClassName,
Expand Down
14 changes: 10 additions & 4 deletions src/table/Cell.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { MouseEvent } from 'react';
import React, { MouseEvent, MutableRefObject } from 'react';
import classNames from 'classnames';
import isFunction from 'lodash/isFunction';
import get from 'lodash/get';
Expand Down Expand Up @@ -27,7 +27,7 @@ export interface CellProps {
cellSpans: RowspanColspan;
cellEmptyContent: TdBaseTableProps['cellEmptyContent'];
tableClassNames: TableClassName;
tableElm?: HTMLDivElement;
tableRef?: MutableRefObject<HTMLDivElement>;
classPrefix?: string;
overlayClassName?: string;
pagination?: PaginationProps;
Expand Down Expand Up @@ -95,7 +95,7 @@ function renderEllipsisCell(cellParams: BaseTableCellParams<TableRowData>, param
}

const Cell = (props: CellProps) => {
const { cellParams, tableClassNames, tableElm, columnLength, classPrefix, overlayClassName, pagination } = props;
const { cellParams, tableClassNames, tableRef, columnLength, classPrefix, overlayClassName, pagination } = props;
const { col, colIndex, rowIndex } = cellParams;
const { cellSpans, dataLength, rowAndColFixedPosition, cellEmptyContent, rowspanAndColspan, onClick } = props;
const { tableColFixedClasses, tdEllipsisClass, tableBaseClass, tdAlignClasses, tableDraggableClasses } =
Expand Down Expand Up @@ -127,7 +127,13 @@ const Cell = (props: CellProps) => {
onClick={onClick}
>
{col.ellipsis
? renderEllipsisCell(cellParams, { cellNode, tableElm, columnLength, classPrefix, overlayClassName })
? renderEllipsisCell(cellParams, {
cellNode,
tableElm: tableRef.current,
columnLength,
classPrefix,
overlayClassName,
})
: cellNode}
</td>
);
Expand Down
149 changes: 84 additions & 65 deletions src/table/TBody.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { useMemo } from 'react';
import React, { MutableRefObject, useMemo } from 'react';
import camelCase from 'lodash/camelCase';
import get from 'lodash/get';
import pick from 'lodash/pick';
import classNames from 'classnames';
import TR, { ROW_LISTENERS, TABLE_PROPS } from './TR';
import { useLocaleReceiver } from '../locale/LocalReceiver';
import useClassName from './hooks/useClassName';
import { TableClassName } from './hooks/useClassName';
import useRowspanAndColspan from './hooks/useRowspanAndColspan';
import { BaseTableProps, RowAndColFixedPosition } from './interface';
import { TdBaseTableProps } from './type';
Expand All @@ -19,13 +19,14 @@ export interface TableBodyProps extends BaseTableProps {
// 固定列 left/right 具体值
rowAndColFixedPosition?: RowAndColFixedPosition;
showColumnShadow?: { left: boolean; right: boolean };
tableElm?: HTMLDivElement;
tableContentElm?: HTMLDivElement;
tableRef?: MutableRefObject<HTMLDivElement>;
tableContentRef?: MutableRefObject<HTMLDivElement>;
cellEmptyContent: TdBaseTableProps['cellEmptyContent'];
tableWidth?: number;
tableWidth?: MutableRefObject<number>;
isWidthOverflow?: boolean;
virtualConfig: VirtualScrollConfig;
pagination?: PaginationProps;
allTableClasses?: TableClassName;
handleRowMounted?: (rowData: any) => void;
}

Expand Down Expand Up @@ -58,10 +59,12 @@ export const extendTableProps = [

export default function TBody(props: TableBodyProps) {
// 如果不是变量复用,没必要对每一个参数进行解构(解构过程需要单独的内存空间存储临时变量)
const { data, columns, rowKey, firstFullRow, lastFullRow, virtualConfig } = props;
const { data, columns, rowKey, firstFullRow, lastFullRow, virtualConfig, allTableClasses } = props;
const [global, t] = useLocaleReceiver('table');
const { tableFullRowClasses, tableBaseClass } = useClassName();
const { tableFullRowClasses, tableBaseClass } = allTableClasses;
const { skipSpansMap } = useRowspanAndColspan(data, columns, rowKey, props.rowspanAndColspan);
const columnLength = columns.length;
const dataLength = data?.length;

const tbodyClasses = useMemo(() => [tableBaseClass.body], [tableBaseClass.body]);
const hasFullRowConfig = useMemo(() => firstFullRow || lastFullRow, [firstFullRow, lastFullRow]);
Expand Down Expand Up @@ -104,69 +107,77 @@ export default function TBody(props: TableBodyProps) {
);
};

const columnLength = columns.length;
const dataLength = data?.length;
const trNodeList = [];

const properties = [
'classPrefix',
'ellipsisOverlayClassName',
'rowAndColFixedPosition',
'scroll',
'tableElm',
'tableContentElm',
'trs',
'bufferSize',
'isVirtual',
'rowHeight',
'scrollType',
];
data?.forEach((row, rowIndex) => {
const trProps = {
...pick(props, TABLE_PROPS),
rowKey: props.rowKey || 'id',
row,
columns,
// eslint-disable-next-line
rowIndex: row.__VIRTUAL_SCROLL_INDEX || rowIndex,
dataLength,
skipSpansMap,
virtualConfig,
classPrefix: props.classPrefix,
ellipsisOverlayClassName: props.ellipsisOverlayClassName,
...pick(props, properties),
pagination: props.pagination,
};
if (props.onCellClick) {
trProps.onCellClick = props.onCellClick;
}

const trNode = (
<TR key={get(row, props.rowKey || 'id') || rowIndex} {...trProps} onRowMounted={props.handleRowMounted}></TR>
);
trNodeList.push(trNode);
const firstFullRowNode = useMemo(
() => getFullRow(columnLength, 'first-full-row'),
// eslint-disable-next-line react-hooks/exhaustive-deps
[firstFullRow, columnLength, getFullRow],
);

// 执行展开行渲染
if (props.renderExpandedRow) {
const p = {
const lastFullRowNode = useMemo(
() => getFullRow(columnLength, 'last-full-row'),
// eslint-disable-next-line react-hooks/exhaustive-deps
[lastFullRow, columnLength, getFullRow],
);

const isSkipSnapsMapNotFinish = Boolean(props.rowspanAndColspan && !skipSpansMap.size);

const getTRNodeList = () => {
if (isSkipSnapsMapNotFinish) return null;
const trNodeList = [];
const properties = [
'classPrefix',
'ellipsisOverlayClassName',
'rowAndColFixedPosition',
'scroll',
'tableRef',
'tableContentRef',
'trs',
'bufferSize',
'isVirtual',
'rowHeight',
'scrollType',
];
data?.forEach((row, rowIndex) => {
const trProps = {
...pick(props, TABLE_PROPS),
rowKey: props.rowKey || 'id',
row,
index: rowIndex,
columns,
tableWidth: props.tableWidth,
isWidthOverflow: props.isWidthOverflow,
// eslint-disable-next-line
rowIndex: row.__VIRTUAL_SCROLL_INDEX || rowIndex,
dataLength,
skipSpansMap,
virtualConfig,
classPrefix: props.classPrefix,
ellipsisOverlayClassName: props.ellipsisOverlayClassName,
...pick(props, properties),
pagination: props.pagination,
};
const expandedContent = props.renderExpandedRow(p);
expandedContent && trNodeList.push(expandedContent);
}
});
if (props.onCellClick) {
trProps.onCellClick = props.onCellClick;
}

const trNode = (
<TR key={get(row, props.rowKey || 'id') || rowIndex} {...trProps} onRowMounted={props.handleRowMounted}></TR>
);
trNodeList.push(trNode);

// 执行展开行渲染
if (props.renderExpandedRow) {
const p = {
row,
index: rowIndex,
columns,
tableWidth: props.tableWidth,
isWidthOverflow: props.isWidthOverflow,
};
const expandedContent = props.renderExpandedRow(p);
expandedContent && trNodeList.push(expandedContent);
}
});
return trNodeList;
};

const list = (
<>
{getFullRow(columnLength, 'first-full-row')}
{trNodeList}
{getFullRow(columnLength, 'last-full-row')}
</>
);
const isEmpty = !data?.length && !props.loading && !hasFullRowConfig;

// 垫上隐藏的 tr 元素高度
Expand All @@ -180,6 +191,14 @@ export default function TBody(props: TableBodyProps) {
}
: undefined;

const list = (
<>
{firstFullRowNode}
{getTRNodeList()}
{lastFullRowNode}
</>
);

return (
<tbody className={classNames(tbodyClasses)} style={{ ...posStyle }}>
{isEmpty ? renderEmpty(columns) : list}
Expand Down
14 changes: 7 additions & 7 deletions src/table/TR.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useMemo, useRef, MouseEvent, useEffect } from 'react';
import React, { useMemo, useRef, MouseEvent, useEffect, MutableRefObject } from 'react';
import get from 'lodash/get';
import classnames from 'classnames';
import { formatRowAttributes, formatRowClassNames } from './utils';
Expand Down Expand Up @@ -52,8 +52,8 @@ export interface TrProps extends TrCommonProps {
trs?: Map<number, object>;
bufferSize?: number;
scroll?: InfinityScroll;
tableElm?: HTMLDivElement;
tableContentElm?: HTMLDivElement;
tableRef?: MutableRefObject<HTMLDivElement>;
tableContentRef?: MutableRefObject<HTMLDivElement>;
pagination?: PaginationProps;
virtualConfig?: VirtualScrollConfig;
onRowMounted?: (data: any) => void;
Expand All @@ -72,7 +72,7 @@ export default function TR(props: TrProps) {
dataLength,
fixedRows,
scroll,
tableContentElm,
tableContentRef,
rowAndColFixedPosition,
virtualConfig,
onRowMounted,
Expand Down Expand Up @@ -102,7 +102,7 @@ export default function TR(props: TrProps) {
}, [row, rowClassName, rowIndex, rowKey, trStyles?.classes]);

const useLazyLoadParams = useMemo(() => ({ ...scroll, rowIndex }), [scroll, rowIndex]);
const { hasLazyLoadHolder, tRowHeight } = useLazyLoad(tableContentElm, trRef, useLazyLoadParams);
const { hasLazyLoadHolder, tRowHeight } = useLazyLoad(tableContentRef.current, trRef, useLazyLoadParams);

useEffect(() => {
if (virtualConfig.isVirtualScroll && trRef.current) {
Expand All @@ -123,7 +123,7 @@ export default function TR(props: TrProps) {
colIndex,
};
let spanState = null;
if (props.skipSpansMap.size) {
if (props.skipSpansMap?.size) {
const cellKey = getCellKey(row, props.rowKey, col.colKey, colIndex);
spanState = props.skipSpansMap.get(cellKey) || {};
spanState?.rowspan > 1 && (cellSpans.rowspan = spanState.rowspan);
Expand All @@ -149,7 +149,7 @@ export default function TR(props: TrProps) {
tableClassNames={classNames}
rowspanAndColspan={props.rowspanAndColspan}
onClick={onClick}
tableElm={props.tableElm}
tableRef={props.tableRef}
classPrefix={props.classPrefix}
overlayClassName={props.ellipsisOverlayClassName}
pagination={props.pagination}
Expand Down
Loading

0 comments on commit 495ddd0

Please sign in to comment.