From a948e663a9334af7e0021c335f98da7bd1666abe Mon Sep 17 00:00:00 2001 From: tangjinzhou <415800467@qq.com> Date: Sat, 4 Sep 2021 17:11:18 +0800 Subject: [PATCH] refactor: table --- components/new-table/Body/BodyRow.tsx | 44 +++--- components/new-table/Body/ExpandedRow.tsx | 48 ++++--- components/new-table/Body/index.tsx | 1 - components/new-table/Cell/index.tsx | 41 ++++-- components/new-table/Footer/Cell.tsx | 4 +- components/new-table/Footer/Row.tsx | 11 +- components/new-table/Footer/Summary.tsx | 31 +++-- components/new-table/Header/Header.tsx | 4 +- components/new-table/Header/HeaderRow.tsx | 1 + components/new-table/Table.tsx | 131 ++++++++++++------ components/new-table/context/TableContext.tsx | 2 + components/new-table/hooks/useColumns.tsx | 6 - components/new-table/interface.ts | 3 +- 13 files changed, 199 insertions(+), 128 deletions(-) diff --git a/components/new-table/Body/BodyRow.tsx b/components/new-table/Body/BodyRow.tsx index ca881d635..6ad4fd3a7 100644 --- a/components/new-table/Body/BodyRow.tsx +++ b/components/new-table/Body/BodyRow.tsx @@ -142,26 +142,6 @@ export default defineComponent>({ const key = columnsKey[colIndex]; const fixedInfo = fixedInfoList[colIndex]; - // ============= Used for nest expandable ============= - let appendCellNode; - if (colIndex === (expandIconColumnIndex || 0) && nestExpandable.value) { - appendCellNode = ( - <> - - {expandIcon({ - prefixCls, - expanded: expanded.value, - expandable: hasNestChildren.value, - record, - onExpand: onInternalTriggerExpand, - })} - - ); - } - let additionalCellProps; if (column.customCell) { additionalCellProps = column.customCell(record, index); @@ -180,8 +160,30 @@ export default defineComponent>({ dataIndex={dataIndex} customRender={customRender} {...fixedInfo} - appendNode={appendCellNode} additionalProps={additionalCellProps} + v-slots={{ + // ============= Used for nest expandable ============= + appendNode: () => { + if (colIndex === (expandIconColumnIndex || 0) && nestExpandable.value) { + return ( + <> + + {expandIcon({ + prefixCls, + expanded: expanded.value, + expandable: hasNestChildren.value, + record, + onExpand: onInternalTriggerExpand, + })} + + ); + } + return null; + }, + }} /> ); })} diff --git a/components/new-table/Body/ExpandedRow.tsx b/components/new-table/Body/ExpandedRow.tsx index 6de09ea3c..9fd429a06 100644 --- a/components/new-table/Body/ExpandedRow.tsx +++ b/components/new-table/Body/ExpandedRow.tsx @@ -43,24 +43,6 @@ export default defineComponent({ colSpan, } = props; - let contentNode: any = slots.default?.(); - - if (fixColumn) { - contentNode = ( -
- {contentNode} -
- ); - } - return ( ({ display: expanded ? null : 'none', }} > - - {contentNode} - + { + let contentNode: any = slots.default?.(); + + if (fixColumn) { + contentNode = ( +
+ {contentNode} +
+ ); + } + return contentNode; + }, + }} + >
); }; diff --git a/components/new-table/Body/index.tsx b/components/new-table/Body/index.tsx index 51fa6c6ae..071adcaba 100644 --- a/components/new-table/Body/index.tsx +++ b/components/new-table/Body/index.tsx @@ -16,7 +16,6 @@ export interface BodyProps { expandedKeys: Set; customRow: GetComponentProps; rowExpandable: (record: RecordType) => boolean; - // emptyNode: React.ReactNode; childrenColumnName: string; } diff --git a/components/new-table/Cell/index.tsx b/components/new-table/Cell/index.tsx index 8367532c5..185c31c8b 100644 --- a/components/new-table/Cell/index.tsx +++ b/components/new-table/Cell/index.tsx @@ -22,14 +22,12 @@ function isRenderCell( export interface CellProps { prefixCls?: string; - className?: string; record?: RecordType; /** `record` index. Not `column` index. */ index?: number; dataIndex?: DataIndex; customRender?: ColumnType['customRender']; component?: CustomizeComponent; - children?: any; colSpan?: number; rowSpan?: number; ellipsis?: CellEllipsisType; @@ -46,6 +44,7 @@ export interface CellProps { // Additional /** @private Used for `expandable` with nest tree */ appendNode?: any; + additionalProps?: HTMLAttributes; rowType?: 'header' | 'body' | 'footer'; @@ -56,18 +55,39 @@ export interface CellProps { } export default defineComponent({ name: 'Cell', - props: [] as any, + props: [ + 'prefixCls', + 'record', + 'index', + 'dataIndex', + 'customRender', + 'children', + 'component', + 'colSpan', + 'rowSpan', + 'fixLeft', + 'fixRight', + 'firstFixLeft', + 'lastFixLeft', + 'firstFixRight', + 'lastFixRight', + 'appendNode', + 'additionalProps', + 'ellipsis', + 'align', + 'rowType', + 'isSticky', + 'column', + ] as any, slots: ['appendNode'], - setup(props) { + setup(props, { slots }) { return () => { const { prefixCls, - className, record, index, dataIndex, customRender, - children, component: Component = 'td', colSpan, rowSpan, @@ -77,7 +97,7 @@ export default defineComponent({ lastFixLeft, firstFixRight, lastFixRight, - appendNode, + appendNode = slots.appendNode?.(), additionalProps = {}, ellipsis, align, @@ -90,7 +110,7 @@ export default defineComponent({ // ==================== Child Node ==================== let cellProps: CellType; let childNode; - + const children = slots.default?.(); if (validateValue(children)) { childNode = children; } else { @@ -127,8 +147,7 @@ export default defineComponent({ colSpan: cellColSpan, rowSpan: cellRowSpan, style: cellStyle, - className: cellClassName, - class: cellClass, + class: cellClassName, ...restCellProps } = cellProps || {}; const mergedColSpan = cellColSpan !== undefined ? cellColSpan : colSpan; @@ -179,7 +198,6 @@ export default defineComponent({ rowSpan: mergedRowSpan && mergedRowSpan !== 1 ? mergedRowSpan : null, class: classNames( cellPrefixCls, - className, { [`${cellPrefixCls}-fix-left`]: isFixLeft, [`${cellPrefixCls}-fix-left-first`]: firstFixLeft, @@ -193,7 +211,6 @@ export default defineComponent({ }, additionalProps.class, cellClassName, - cellClass, ), style: { ...parseStyleText(additionalProps.style as any), diff --git a/components/new-table/Footer/Cell.tsx b/components/new-table/Footer/Cell.tsx index 043800fce..69bb032bb 100644 --- a/components/new-table/Footer/Cell.tsx +++ b/components/new-table/Footer/Cell.tsx @@ -6,8 +6,6 @@ import type { AlignType } from '../interface'; import { getCellFixedInfo } from '../utils/fixUtil'; export interface SummaryCellProps { - className?: string; - children?: any; index: number; colSpan?: number; rowSpan?: number; @@ -38,7 +36,7 @@ export default defineComponent({ return ( {slots.default?.()}; -} +import { defineComponent } from 'vue'; + +export default defineComponent({ + name: 'FooterRow', + setup(_props, { slots }) { + return () => {slots.default?.()}; + }, +}); diff --git a/components/new-table/Footer/Summary.tsx b/components/new-table/Footer/Summary.tsx index 9e22280cf..9a6f3e2ab 100644 --- a/components/new-table/Footer/Summary.tsx +++ b/components/new-table/Footer/Summary.tsx @@ -1,4 +1,5 @@ -import { FunctionalComponent } from 'vue'; +import { computed, defineComponent, FunctionalComponent, onBeforeUnmount, watchEffect } from 'vue'; +import { useInjectTable } from '../context/TableContext'; import Cell from './Cell'; import Row from './Row'; @@ -11,16 +12,22 @@ export interface SummaryFC extends FunctionalComponent { Cell: typeof Cell; } -/** - * Syntactic sugar. Do not support HOC. - */ -const Summary: SummaryFC = (_props, { slots }) => { - return slots.default?.(); -}; - -Summary.Row = Row; -Summary.Cell = Cell; - -Summary.displayName = 'Summary'; +let indexGuid = 0; +const Summary = defineComponent({ + props: ['fixed'] as any, + name: 'Summary', + setup(props, { slots }) { + const tableContext = useInjectTable(); + const uniKey = `table-summary-uni-key-${++indexGuid}`; + const fixed = computed(() => (props.fixed as string) === '' || props.fixed); + watchEffect(() => { + tableContext.summaryCollect(uniKey, fixed.value); + }); + onBeforeUnmount(() => { + tableContext.summaryCollect(uniKey, false); + }); + return () => slots.default?.(); + }, +}); export default Summary; diff --git a/components/new-table/Header/Header.tsx b/components/new-table/Header/Header.tsx index 81f528565..2ffd6e346 100644 --- a/components/new-table/Header/Header.tsx +++ b/components/new-table/Header/Header.tsx @@ -29,8 +29,8 @@ function parseHeaderRows( const colSpans: number[] = columns.filter(Boolean).map(column => { const cell: CellType = { key: column.key, - className: classNames(column.className, column.class), - children: column.title, + class: classNames(column.className, column.class), + // children: column.title, column, colStart: currentColIndex, }; diff --git a/components/new-table/Header/HeaderRow.tsx b/components/new-table/Header/HeaderRow.tsx index 5a50c834e..5fc400b6b 100644 --- a/components/new-table/Header/HeaderRow.tsx +++ b/components/new-table/Header/HeaderRow.tsx @@ -86,6 +86,7 @@ export default defineComponent({ additionalProps={additionalProps} rowType="header" column={column} + v-slots={{ default: () => column.title }} /> ); })} diff --git a/components/new-table/Table.tsx b/components/new-table/Table.tsx index 83630564a..878aab826 100644 --- a/components/new-table/Table.tsx +++ b/components/new-table/Table.tsx @@ -1,26 +1,20 @@ -import ColumnGroup from './sugar/ColumnGroup'; -import Column from './sugar/Column'; import Header from './Header/Header'; import type { GetRowKey, ColumnsType, TableComponents, Key, - DefaultRecordType, TriggerEventHandler, GetComponentProps, ExpandableConfig, LegacyExpandableProps, - GetComponent, PanelRender, TableLayout, - ExpandableType, RowClassName, CustomizeComponent, ColumnType, CustomizeScrollBody, TableSticky, - FixedType, } from './interface'; import Body from './Body'; import useColumns from './hooks/useColumns'; @@ -28,16 +22,13 @@ import { useLayoutState, useTimeoutLock } from './hooks/useFrame'; import { getPathValue, mergeObject, validateValue, getColumnsKey } from './utils/valueUtil'; import useStickyOffsets from './hooks/useStickyOffsets'; import ColGroup from './ColGroup'; -import { getExpandableProps, getDataAndAriaProps } from './utils/legacyUtil'; import Panel from './Panel'; -import Footer, { FooterComponents } from './Footer'; +import Footer from './Footer'; import { findAllChildrenKeys, renderExpandIcon } from './utils/expandUtil'; import { getCellFixedInfo } from './utils/fixUtil'; import StickyScrollBar from './stickyScrollBar'; import useSticky from './hooks/useSticky'; import FixedHolder from './FixedHolder'; -import type { SummaryProps } from './Footer/Summary'; -import Summary from './Footer/Summary'; import { computed, CSSProperties, @@ -59,6 +50,10 @@ import isVisible from '../vc-util/Dom/isVisible'; import { getTargetScrollBarSize } from '../_util/getScrollBarSize'; import classNames from '../_util/classNames'; import { EventHandler } from '../_util/EventInterface'; +import VCResizeObserver from '../vc-resize-observer'; +import { useProvideTable } from './context/TableContext'; +import { useProvideBody } from './context/BodyContext'; +import { useProvideResize } from './context/ResizeContext'; // Used for conditions cache const EMPTY_DATA = []; @@ -85,8 +80,8 @@ export interface TableProps extends LegacyExpandableProps< rowClassName?: string | RowClassName; // Additional Part - // title?: PanelRender; - // footer?: PanelRender; + title?: PanelRender; + footer?: PanelRender; // summary?: (data: readonly RecordType[]) => any; // Customize @@ -103,40 +98,14 @@ export interface TableProps extends LegacyExpandableProps< expandColumnWidth?: number; expandIconColumnIndex?: number; - // // =================================== Internal =================================== - // /** - // * @private Internal usage, may remove by refactor. Should always use `columns` instead. - // * - // * !!! DO NOT USE IN PRODUCTION ENVIRONMENT !!! - // */ - // internalHooks?: string; - - // /** - // * @private Internal usage, may remove by refactor. Should always use `columns` instead. - // * - // * !!! DO NOT USE IN PRODUCTION ENVIRONMENT !!! - // */ - // // Used for antd table transform column with additional column - // transformColumns?: (columns: ColumnsType) => ColumnsType; - - // /** - // * @private Internal usage, may remove by refactor. - // * - // * !!! DO NOT USE IN PRODUCTION ENVIRONMENT !!! - // */ - // internalRefs?: { - // body: React.MutableRefObject; - // }; - sticky?: boolean | TableSticky; } export default defineComponent({ name: 'Table', slots: ['title', 'footer', 'summary', 'emptyText'], - inheritAttrs: false, emits: ['expand', 'expandedRowsChange'], - setup(props, { slots, attrs, emit }) { + setup(props, { slots, emit }) { const mergedData = computed(() => props.data || EMPTY_DATA); const hasData = computed(() => !!mergedData.value.length); @@ -432,13 +401,58 @@ export default defineComponent({ const emptyNode = () => { return hasData.value ? null : slots.emptyText?.() || 'No Data'; }; + useProvideTable( + reactive({ + ...reactivePick(props, 'prefixCls', 'direction'), + getComponent, + scrollbarSize, + fixedInfoList: computed(() => + flattenColumns.value.map((_, colIndex) => + getCellFixedInfo( + colIndex, + colIndex, + flattenColumns.value, + stickyOffsets.value, + props.direction, + ), + ), + ), + isSticky: computed(() => stickyState.value.isSticky), + summaryCollect, + }), + ); + + useProvideBody( + reactive({ + ...reactivePick( + props, + 'rowClassName', + 'expandedRowClassName', + 'expandRowByClick', + 'expandedRowRender', + 'expandIconColumnIndex', + 'indentSize', + ), + columns, + flattenColumns, + tableLayout: mergedTableLayout, + componentWidth, + fixHeader, + fixColumn, + horizonScroll, + expandIcon: mergedExpandIcon, + expandableType, + onTriggerExpand, + }), + ); + + useProvideResize({ + onColumnResize, + }); return () => { const { prefixCls, - rowClassName, - data, - rowKey, scroll, tableLayout, direction, @@ -450,10 +464,8 @@ export default defineComponent({ // Customize id, showHeader, - components, customHeaderRow, rowExpandable, - sticky, customRow, } = props; @@ -648,7 +660,36 @@ export default defineComponent({ ); } - return null; + + let fullTable = ( +
+ {title && {title(mergedData.value)}} +
{groupTableNode}
+ {footer && {footer(mergedData.value)}} +
+ ); + + if (horizonScroll.value) { + fullTable = {fullTable}; + } + return fullTable; }; }, }); diff --git a/components/new-table/context/TableContext.tsx b/components/new-table/context/TableContext.tsx index 557007418..4ad3f79bc 100644 --- a/components/new-table/context/TableContext.tsx +++ b/components/new-table/context/TableContext.tsx @@ -15,6 +15,8 @@ export interface TableContextProps { fixedInfoList: readonly FixedInfo[]; isSticky: boolean; + + summaryCollect: (uniKey: string, fixed: boolean | string) => void; } export const BodyContextKey: InjectionKey = Symbol('TableContextProps'); diff --git a/components/new-table/hooks/useColumns.tsx b/components/new-table/hooks/useColumns.tsx index f832c8693..ad30c5265 100644 --- a/components/new-table/hooks/useColumns.tsx +++ b/components/new-table/hooks/useColumns.tsx @@ -120,7 +120,6 @@ function useColumns({ }: { prefixCls?: Ref; columns?: Ref>; - // children?: React.ReactNode; expandable: Ref; expandedKeys: Ref>; getRowKey: Ref>; @@ -134,11 +133,6 @@ function useColumns({ expandFixed?: Ref; }): // transformColumns: (columns: ColumnsType) => ColumnsType, [ComputedRef>, ComputedRef[]>] { - // const baseColumns = React.useMemo>( - // () => columns || convertChildrenToColumns(children), - // [columns, children], - // ); - // Add expand column const withExpandColumns = computed>(() => { if (expandable.value) { diff --git a/components/new-table/interface.ts b/components/new-table/interface.ts index 0a5d3845a..2557845dc 100644 --- a/components/new-table/interface.ts +++ b/components/new-table/interface.ts @@ -36,9 +36,8 @@ export type RowClassName = ( export interface CellType { key?: Key; class?: string; - className?: string; style?: CSSProperties; - children?: any; + // children?: any; column?: ColumnsType[number]; colSpan?: number; rowSpan?: number;