diff --git a/packages/s2-core/src/data-set/base-data-set.ts b/packages/s2-core/src/data-set/base-data-set.ts index dd3f1666f5..638ebe453a 100644 --- a/packages/s2-core/src/data-set/base-data-set.ts +++ b/packages/s2-core/src/data-set/base-data-set.ts @@ -235,7 +235,7 @@ export abstract class BaseDataSet { } public getDisplayDataSet() { - return this.displayData; + return this.displayData || []; } public isEmpty() { diff --git a/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/edit-cell/index.tsx b/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/edit-cell/index.tsx index 458bf6a316..d2b2af977a 100644 --- a/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/edit-cell/index.tsx +++ b/packages/s2-react/src/components/sheets/editable-sheet/custom-cell/edit-cell/index.tsx @@ -6,6 +6,7 @@ import { type DataItem, type S2CellType, type ViewMeta, + type RawData, } from '@antv/s2'; import { Input } from 'antd'; import { isNil, merge, pick } from 'lodash'; @@ -27,15 +28,15 @@ import './index.less'; export interface CustomProps { style: React.CSSProperties; - onChange: (val: string) => void; + onChange: (value: string) => void; onSave: () => void; value: DataItem; spreadsheet: SpreadSheet; cell: S2CellType | null; } -type onChangeProps = { - onChange?: (val: any[]) => void; +type EditCellProps = { + onChange?: (val: RawData[]) => void; onDataCellEditEnd?: (meta: ViewMeta) => void; trigger?: number; CustomComponent?: React.FunctionComponent; @@ -44,7 +45,7 @@ type onChangeProps = { const EDIT_CELL_CLASS = `${S2_PREFIX_CLS}-edit-cell`; function EditCellComponent( - props: InvokeComponentProps<{ cell: S2CellType } & onChangeProps>, + props: InvokeComponentProps<{ cell: S2CellType } & EditCellProps>, ) { const { params, resolver } = props; const s2 = useSpreadSheetInstance(); @@ -97,27 +98,30 @@ function EditCellComponent( const inputRef = useRef(null); const containerRef = useRef(null); + /** + * 在 Enter 确定输入后,会执行 onSave 逻辑,然后组件被销毁后,又会通过 blur 再执行一遍,这个时候 displayData 顺序已经变了,再执行获取的 rowIndex 是错误的 + * 本质上,还是和 invokeComponent 中在移除 dom 节点前,没有提前 unmount 组件有关(1.x 中进行了处理,2.x 中现在只对其中一个分支处理了) + * */ + const hasSaved = useRef(false); + useEffect(() => { setTimeout(() => { // 防止触发表格全选 - if (containerRef.current) { - containerRef.current!.click(); - } - - if (inputRef.current) { - inputRef.current!.focus(); - } + containerRef.current?.click(); + // 开启 preventScroll, 防止页面有滚动条时触发滚动 + inputRef.current?.focus({ preventScroll: true }); }); }, []); const onSave = () => { - if (!cell) { + if (!cell || hasSaved.current) { return; } const { rowIndex, valueField } = cell.getMeta(); + const displayData = s2.dataSet.getDisplayDataSet(); - s2.dataSet.originData[rowIndex][valueField] = inputVal; + displayData[rowIndex][valueField] = inputVal; s2.render(true); const meta = merge(cell.getMeta(), { @@ -131,19 +135,13 @@ function EditCellComponent( onDataCellEditEnd?.(meta); if (onChange) { - onChange(s2.dataSet.originData); + onChange(displayData); } + hasSaved.current = true; resolver(true); }; - const onKeyDown: React.KeyboardEventHandler = (e) => { - if (e.keyCode === 13) { - e.preventDefault(); - onSave(); - } - }; - const styleProps: React.CSSProperties = { left: cellLeft, top: cellTop, @@ -152,7 +150,7 @@ function EditCellComponent( zIndex: 1000, }; - const changeValue = (val: string) => { + const onChangeValue = (val: string) => { setInputVal(val); }; @@ -175,7 +173,7 @@ function EditCellComponent( spreadsheet={s2} value={inputVal} style={styleProps} - onChange={changeValue} + onChange={onChangeValue} onSave={onSave} /> ) : ( @@ -189,32 +187,34 @@ function EditCellComponent( setInputVal(e.target.value); }} onBlur={onSave} - onKeyDown={onKeyDown} + onPressEnter={onSave} /> )} ); } -export const EditCell = memo(({ onChange, CustomComponent }: onChangeProps) => { - const spreadsheet = useSpreadSheetInstance(); +export const EditCell = memo(({ onChange, CustomComponent }: EditCellProps) => { + const s2 = useSpreadSheetInstance(); const onEditCell = useCallback( (event: GEvent) => { invokeComponent({ component: EditCellComponent, params: { - cell: spreadsheet.getCell(event.target)!, + cell: s2.getCell(event.target)!, onChange, CustomComponent, }, - spreadsheet, + s2, }); }, - [CustomComponent, onChange, spreadsheet], + [CustomComponent, onChange, s2], ); - useS2Event(S2Event.DATA_CELL_CLICK, onEditCell, spreadsheet); + useS2Event(S2Event.DATA_CELL_CLICK, onEditCell, s2); return null; }); + +EditCell.displayName = 'EditCell'; diff --git a/packages/s2-react/src/components/sheets/editable-sheet/drag-copy/drag-copy-mask.tsx b/packages/s2-react/src/components/sheets/editable-sheet/drag-copy/drag-copy-mask.tsx index 0cf5a9cd70..bc3d64243f 100644 --- a/packages/s2-react/src/components/sheets/editable-sheet/drag-copy/drag-copy-mask.tsx +++ b/packages/s2-react/src/components/sheets/editable-sheet/drag-copy/drag-copy-mask.tsx @@ -131,17 +131,15 @@ export const DragCopyMask = memo(({ onCopyFinished }: DragCopyProps) => { }, 10); const dragMouseUp = (event: MouseEvent) => { - let targetCell = getCurrentHoverCell(event); - if (!startCell) { return; } - if (!targetCell) { - targetCell = getCurrentHoverCell(lastHoverPoint as MouseEvent); - } + const targetCell = + getCurrentHoverCell(event) || + getCurrentHoverCell(lastHoverPoint as MouseEvent); - const source = spreadsheet.dataSet.originData; + const displayData = spreadsheet.dataSet.getDisplayDataSet(); const selectedRange = getSelectedCellRange(startCell, targetCell!); const { fieldValue } = startCell.getMeta(); @@ -149,10 +147,10 @@ export const DragCopyMask = memo(({ onCopyFinished }: DragCopyProps) => { const { rowIndex, valueField } = item.getMeta(); if ( - source[rowIndex] && - typeof source[rowIndex][valueField] !== 'undefined' + displayData[rowIndex] && + typeof displayData[rowIndex][valueField] !== 'undefined' ) { - source[rowIndex][valueField] = fieldValue; + displayData[rowIndex][valueField] = fieldValue; } return item; diff --git a/packages/s2-react/src/components/sheets/editable-sheet/drag-copy/index.tsx b/packages/s2-react/src/components/sheets/editable-sheet/drag-copy/index.tsx index c60435acc5..6d07c73a04 100644 --- a/packages/s2-react/src/components/sheets/editable-sheet/drag-copy/index.tsx +++ b/packages/s2-react/src/components/sheets/editable-sheet/drag-copy/index.tsx @@ -137,7 +137,6 @@ export function DragCopyPoint() { useS2Event(S2Event.ROW_CELL_CLICK, batchSelected, spreadsheet); useS2Event(S2Event.CORNER_CELL_CLICK, batchSelected, spreadsheet); useS2Event(S2Event.DATA_CELL_BRUSH_SELECTION, batchSelected, spreadsheet); - useS2Event(S2Event.DATA_CELL_CLICK, fixPosition, spreadsheet); return ( diff --git a/packages/s2-react/src/utils/invokeComponent.tsx b/packages/s2-react/src/utils/invokeComponent.tsx index 8cda512d02..776c5f9854 100644 --- a/packages/s2-react/src/utils/invokeComponent.tsx +++ b/packages/s2-react/src/utils/invokeComponent.tsx @@ -1,6 +1,6 @@ import type { SpreadSheet } from '@antv/s2'; import React from 'react'; -import { createRoot } from 'react-dom/client'; +import { createRoot, type Root } from 'react-dom/client'; import { SpreadSheetContext } from '../context/SpreadSheetContext'; export type InvokeComponentProps

= { @@ -12,7 +12,7 @@ export type InvokeComponentProps

= { export type InvokeComponentOptions

= { component: React.ComponentType>; params: P; - spreadsheet: SpreadSheet; + s2: SpreadSheet; id?: string; onCleanup?: () => void; }; @@ -21,7 +21,7 @@ export type InvokeComponentOptions

= { * 挂载组件 */ export function invokeComponent

(options: InvokeComponentOptions

) { - const { id, spreadsheet, params, onCleanup, component: Component } = options; + const { id, s2, params, onCleanup, component: Component } = options; if (id) { const domNode = document.querySelector(`#${id}`); @@ -37,6 +37,7 @@ export function invokeComponent

(options: InvokeComponentOptions

) { } } + let root: Root; const container = document.createElement('div'); if (id) { @@ -49,8 +50,7 @@ export function invokeComponent

(options: InvokeComponentOptions

) { let rejectCb: (reason?: unknown) => void; function destroy() { - // const unmountResult = ReactDOM.unmountComponentAtNode(container); - + root?.unmount(); if (container.parentNode) { container.parentNode.removeChild(container); @@ -76,8 +76,10 @@ export function invokeComponent

(options: InvokeComponentOptions

) { function render() { setTimeout(() => { - createRoot(container!).render( - + root = createRoot(container!); + + root.render( + , );