diff --git a/docs/examples/fixedColumns-resize.tsx b/docs/examples/fixedColumns-resize.tsx index c3a35b678..85793b155 100644 --- a/docs/examples/fixedColumns-resize.tsx +++ b/docs/examples/fixedColumns-resize.tsx @@ -1,7 +1,7 @@ -import React, { useState, useCallback } from 'react'; +import type { ColumnGroupType, ColumnType } from '@/interface'; import Table from 'rc-table'; +import React, { useCallback, useState } from 'react'; import '../../assets/index.less'; -import type { ColumnType } from '@/interface'; interface RecordType { a: string; @@ -11,9 +11,15 @@ interface RecordType { key: string; } -const defaultColumns: ColumnType[] = [ - { title: 'title1', dataIndex: 'a', key: 'a', width: 100, fixed: 'left' }, - { title: 'title2', dataIndex: 'b', key: 'b', width: 100, fixed: 'left', ellipsis: true }, +const defaultColumns: (ColumnType | ColumnGroupType)[] = [ + { + title: 'firstGroup', + fixed: 'left', + children: [ + { title: 'title1', dataIndex: 'a', key: 'a', width: 100, fixed: 'left' }, + { title: 'title2', dataIndex: 'b', key: 'b', width: 100, ellipsis: true }, + ], + }, { title: 'title3', dataIndex: 'c', key: 'c' }, { title: 'title4', dataIndex: 'b', key: 'd' }, { title: 'title5', dataIndex: 'b', key: 'e' }, @@ -28,8 +34,13 @@ const defaultColumns: ColumnType[] = [ { title: 'title16', dataIndex: 'b', key: 'j5' }, { title: 'title17', dataIndex: 'b', key: 'j6' }, { title: 'title18', dataIndex: 'b', key: 'j7' }, - { title: 'title19', dataIndex: 'b', key: 'k', width: 50, fixed: 'right' }, - { title: 'title20', dataIndex: 'b', key: 'l', width: 100, fixed: 'right' }, + { + title: 'lastGroup', + children: [ + { title: 'title19', dataIndex: 'b', key: 'k', width: 50 }, + { title: 'title20', dataIndex: 'b', key: 'l', width: 100, fixed: 'right' }, + ], + }, ]; const data: RecordType[] = Array.from(new Array(200).fill(1), (v, index) => { @@ -45,6 +56,7 @@ const Demo = () => { const [isShown, setIsShown] = useState(false); const [renderTime, setRenderTime] = useState(0); const [isFixed, setIsFixed] = useState(true); + const [direction, setDirection] = useState<'ltr' | 'rtl'>('ltr'); const [columns, setColumns] = useState(defaultColumns); const onToggleSideBar = useCallback(() => { const s = window.performance.now(); @@ -82,6 +94,10 @@ const Demo = () => { }); }, []); + const onLayoutChange = useCallback(() => { + setDirection(preState => (preState === 'ltr' ? 'rtl' : 'ltr')); + }, []); + const expandedRowRender = useCallback(({ b, c }) => b || c, []); return ( @@ -91,6 +107,7 @@ const Demo = () => { +

更新用时:{renderTime} ms

{
( + column: ColumnType | ColumnGroupType, +): boolean { + // no children only + if (!(column as ColumnGroupType)?.children) { + return true; + } + if ( + (column as ColumnGroupType)?.children && + (column as ColumnGroupType)?.children.length > 0 + ) { + return (column as ColumnGroupType)?.children.some(children => + hasColumnChildren(children), + ); + } +} + export function getCellFixedInfo( colStart: number, colEnd: number, @@ -33,9 +50,10 @@ export function getCellFixedInfo( let fixLeft: number; let fixRight: number; - if (startColumn.fixed === 'left') { + // RTL layout calculation logic processing + if (startColumn.fixed === 'left' || endColumn.fixed === 'left') { fixLeft = stickyOffsets.left[direction === 'rtl' ? colEnd : colStart]; - } else if (endColumn.fixed === 'right') { + } else if (endColumn.fixed === 'right' || startColumn.fixed === 'right') { fixRight = stickyOffsets.right[direction === 'rtl' ? colStart : colEnd]; } @@ -48,23 +66,26 @@ export function getCellFixedInfo( const nextColumn = columns[colEnd + 1]; const prevColumn = columns[colStart - 1]; + // iff all children of a cell have exactly one child, then onlyChildren is true + const hasChildren = hasColumnChildren(curColumns); + // no children only const canLastFix = !(curColumns as ColumnGroupType)?.children; if (direction === 'rtl') { if (fixLeft !== undefined) { const prevFixLeft = prevColumn && prevColumn.fixed === 'left'; - firstFixLeft = !prevFixLeft && canLastFix; + firstFixLeft = !prevFixLeft && (canLastFix || hasChildren); } else if (fixRight !== undefined) { const nextFixRight = nextColumn && nextColumn.fixed === 'right'; - lastFixRight = !nextFixRight && canLastFix; + lastFixRight = !nextFixRight && (canLastFix || hasChildren); } } else if (fixLeft !== undefined) { const nextFixLeft = nextColumn && nextColumn.fixed === 'left'; lastFixLeft = !nextFixLeft && canLastFix; } else if (fixRight !== undefined) { const prevFixRight = prevColumn && prevColumn.fixed === 'right'; - firstFixRight = !prevFixRight && canLastFix; + firstFixRight = !prevFixRight && (canLastFix || hasChildren); } return { diff --git a/tests/FixedColumn.spec.jsx b/tests/FixedColumn.spec.jsx index a0f7eb47a..33a57f510 100644 --- a/tests/FixedColumn.spec.jsx +++ b/tests/FixedColumn.spec.jsx @@ -282,4 +282,42 @@ describe('Table.FixedColumn', () => { await safeAct(wrapper); expect(wrapper.find('.rc-table-cell-fix-left-all')).toHaveLength(10); }); + + describe('freeze column effect under multi-level header', () => { + let wrapper; + + // freeze column data for columns + const customColumns = [ + ...columns.slice(0, columns.length - 2), + { + title: 'title12', + children: [ + { title: 'title13', dataIndex: 'b', key: 'k' }, + { title: 'title14', dataIndex: 'b', key: 'l', width: 100, fixed: 'right' }, + ], + }, + ]; + + beforeEach(() => { + act(() => { + wrapper = mount(
); + }); + }); + + afterEach(() => { + wrapper.unmount(); + }); + + it('table header only has two frozen column cells', async () => { + expect(wrapper.find('.rc-table-thead .rc-table-cell-fix-right-first')).toHaveLength(2); + }); + + it('freeze column cells at the end of the corresponding row', async () => { + const tr = wrapper.find('.rc-table-thead tr'); + + tr.forEach(trElement => { + expect(trElement.find('th').last().hasClass('rc-table-cell-fix-right-first')).toBeTruthy(); + }); + }); + }); });