Skip to content

Commit

Permalink
fix: memo cell
Browse files Browse the repository at this point in the history
  • Loading branch information
linxianxi committed Mar 26, 2024
1 parent 196233e commit 87649b0
Show file tree
Hide file tree
Showing 22 changed files with 381 additions and 318 deletions.
5 changes: 1 addition & 4 deletions .dumirc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,5 @@ export default defineConfig({
html2sketch: {},
mfsu: false,
outputPath: '.doc',
locales: [
{ id: 'en-US', name: 'EN' },
{ id: 'zh-CN', name: '中文' },
],
locales: [{ id: 'zh-CN', name: '中文' }],
});
2 changes: 1 addition & 1 deletion docs/editors/CellDate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const CellDate: React.FC<CellDateProps> = ({ value, fieldProps, render, cellProp
if (mode === 'read') {
childrenNode = (
<>
{dayjs(value).format('YYYY-MM-DD')}
{value ? dayjs(value).format('YYYY-MM-DD') : ''}
{editable && mode === 'read' && (
<div className="cell-icon" onClick={() => setMode('edit')}>
<CaretDownOutlined />
Expand Down
File renamed without changes.
3 changes: 1 addition & 2 deletions docs/examples/components.tsx → docs/examples/add-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import CellDate from '../editors/CellDate';
import CellInput from '../editors/CellInput';
import CellNumber from '../editors/CellNumber';
import CellSingle from '../editors/CellSingle';
import './components.scss';
import './add-icon.scss';

const data = new Array(10).fill(null).map((_, index) => ({
id: index,
Expand Down Expand Up @@ -92,7 +92,6 @@ export default () => {
width: 200,
},
]}
pagination={false}
onSave={({ field, value, index }) => {
setDataSource((prev) => {
const result = [...prev];
Expand Down
1 change: 0 additions & 1 deletion docs/examples/basic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ export default () => {
width: 200,
},
]}
pagination={false}
onSave={({ field, value, index }) => {
setDataSource((prev) => {
const result = [...prev];
Expand Down
188 changes: 188 additions & 0 deletions docs/examples/selectable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { App, Dropdown, Table } from 'antd';
import EditableTable from 'antd-table-editable';
import type { HTMLAttributes } from 'react';
import React, { useCallback, useMemo } from 'react';
import Selectable, { useSelectable } from 'react-selectable-box';
import CellDate from '../editors/CellDate';
import CellInput from '../editors/CellInput';
import CellNumber from '../editors/CellNumber';
import CellSingle from '../editors/CellSingle';
import './basic.scss';

type ValueType = { rowKey: React.Key; dataIndex: string };

const compareFn = (a: ValueType, b: ValueType) =>
a.rowKey === b.rowKey && a.dataIndex === b.dataIndex;

interface CellProps extends HTMLAttributes<HTMLTableCellElement> {
rowKey: React.Key;
dataIndex: string;
onReset: () => void;
}

const Cell = React.forwardRef<HTMLTableCellElement, CellProps>(
({ rowKey, dataIndex, onReset, ...props }, ref) => {
const { setNodeRef, isAdding, isSelected } = useSelectable({
value: { rowKey, dataIndex },
});

let backgroundColor;
if (isSelected) {
backgroundColor = '#d9dff0';
} else if (isAdding) {
backgroundColor = '#e3f2ff';
}

const cellNode = (
<td
ref={(el) => {
setNodeRef(el);
if (ref) {
(ref as any).current = el;
}
}}
{...props}
style={{
...props.style,
backgroundColor,
}}
>
{props.children}
</td>
);

return isSelected ? (
<Dropdown
trigger={['contextMenu']}
menu={{ items: [{ key: '1', label: '清空', onClick: onReset }] }}
>
{cellNode}
</Dropdown>
) : (
cellNode
);
},
);

interface DataType {
key: React.Key;
text: string;
}

const data: DataType[] = [];
for (let i = 0; i < 10; i++) {
data.push({
key: i,
text: 'text',
});
}

export default () => {
const { message } = App.useApp();
const [dataSource, setDataSource] = React.useState(data);
const [value, setValue] = React.useState<ValueType[]>([]);
const tblRef: Parameters<typeof Table>[0]['ref'] = React.useRef(null);

const onReset = useCallback(() => {
setDataSource((prev) => {
const result = [...prev];
value.forEach((item) => {
const index = result.findIndex((i) => i.key === item.rowKey);
result[index] = { ...result[index], [item.dataIndex]: undefined };
});
return result;
});
setValue([]);
}, [value]);

const MemoCell = useMemo(() => {
return React.forwardRef((props: any, ref) => <Cell {...props} ref={ref} onReset={onReset} />);
}, [onReset]);

return (
<Selectable
value={value}
scrollContainer={() => tblRef.current?.nativeElement.querySelector('.ant-table-content')!}
// because item value is an object, so you need to customize the comparison
compareFn={compareFn}
onStart={() => setValue([])}
onEnd={(selectingValue) => {
setValue(selectingValue);
}}
>
<EditableTable
ref={tblRef}
// because table is scrollable, so you should set scrollContainer to Selectable
scroll={{ x: 800 }}
editorComponents={{
text: CellInput,
number: CellNumber,
single: CellSingle,
date: CellDate,
}}
dataSource={dataSource}
components={{
body: {
cell: MemoCell,
},
}}
columns={[
{
title: '文本',
dataIndex: 'text',
editorType: 'text',
editable: true,
width: 200,
formItemProps: {
rules: [{ max: 6, message: 'max length 6' }],
},
},
{
title: '数值',
dataIndex: 'number',
editorType: 'number',
editable: true,
width: 200,
},
{
title: '单选',
dataIndex: 'single',
editorType: 'single',
editable: true,
fieldProps: {
options: [
{ label: 'option1', value: 'a' },
{ label: 'option2', value: 'b' },
{ label: 'option3', value: 'c' },
{ label: 'option4', value: 'd' },
],
},
width: 200,
},
{
title: '日期',
dataIndex: 'date',
editorType: 'date',
editable: true,
width: 200,
},
].map((col) => ({
...col,
onCell: (record: DataType) =>
({
rowKey: record.key,
dataIndex: (col as any).dataIndex,
} as any),
}))}
onSave={({ field, value, index }) => {
setDataSource((prev) => {
const result = [...prev];
result[index] = { ...result[index], [field]: value };
return result;
});
message.success('保存成功');
}}
/>
</Selectable>
);
};
52 changes: 52 additions & 0 deletions docs/guides/Instructions.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
title: 使用须知
group:
title: 快速上手
order: 0
order: 1
nav: 快速上手
---

### 1、在格子被选中时,会向格子添加 `ant-table-cell-selected` class,可自行对其设置样式

### 2、不支持可展开表格,如果你真的需要可以提 issue

### 3、底层使用 `components.body.cell` 实现,但你能继续使用 `components.body.cell` ,且不会覆盖编辑的功能。

### 4、内部已经默认对 Cell 进行了 memo 处理,onSave 只会对单个 Cell 进行重渲染,但在以下这些情况需要注意:

`columns` 里对单个 `column` 进行设置 `formItemProps``fieldProps` 时,如果值直接是个对象,里面的函数必须都要被 `useCallback` 包裹,例如

```typescript
const onClick = useCallback(() => {
// ...
}, []);

const columns = [
{
dataIndex: 'name',
fieldProps: {
onClick,
},
},
];
```

`formItemProps``fieldProps` 是个函数时,也要被 `useCallback` 包裹,例如

```typescript
const fieldProps = useCallback((value, record, index) => {
return {
onClick: () => {
// ...
},
};
}, []);

const columns = [
{
dataIndex: 'name',
fieldProps,
},
];
```
11 changes: 11 additions & 0 deletions docs/guides/add-icon.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: 统一添加 icon
group:
title: 示例
order: 1
order: 1
---

### 使用 components.body.cell 统一添加编辑 icon

<code src="../examples/add-icon.tsx"></code>
67 changes: 0 additions & 67 deletions docs/guides/api.md

This file was deleted.

10 changes: 1 addition & 9 deletions docs/guides/api.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,14 @@ order: 0
nav: 快速上手
---

### 说明

1、底层使用 `components.body.cell` 实现,但你能继续使用 `components.body.cell` ,且不会覆盖编辑的功能。

2、内部已经默认对 Cell 进行了 memo 处理,onSave 只会对单个 Cell 进行重渲染,但在以下这些情况需要注意:[性能优化](/zh-CN/guides/perf)

### Table

| 参数 | 说明 | 类型 |
| ---------------- | -------- | -------------------------------------------------------------------------------------------- |
| editorComponents | 编辑控件 | Record<string, React.FunctionComponent\<any>> |
| onSave | 保存回调 | (info: { field: string; value: any; record: any; index: number; valueType: string }) => void |

### Columns

在格子被选中时,会向格子添加 `ant-table-cell-selected` class,可自行对其设置样式
### Column

| 参数 | 说明 | 类型 |
| -------------- | ------------------- | -------------------------------------------------------------------- |
Expand Down
Loading

0 comments on commit 87649b0

Please sign in to comment.