--- order: 23 title: en-US: Editable Cells zh-CN: 可编辑单元格 --- ## zh-CN 带单元格编辑功能的表格。 ## en-US Table with editable cells. ```tsx import React, { useContext, useState, useEffect, useRef } from 'react'; import { Table, Input, Button, Popconfirm, Form } from 'antd'; const EditableContext = React.createContext(); interface Item { key: string; name: string; age: string; address: string; } interface EditableRowProps { index: number; } const EditableRow: React.FC = ({ index, ...props }) => { const [form] = Form.useForm(); return (
); }; interface EditableCellProps { title: React.ReactNode; editable: boolean; children: React.ReactNode; dataIndex: string; record: Item; handleSave: (record: Item) => void; } const EditableCell: React.FC = ({ title, editable, children, dataIndex, record, handleSave, ...restProps }) => { const [editing, setEditing] = useState(false); const inputRef = useRef(); const form = useContext(EditableContext); useEffect(() => { if (editing) { inputRef.current.focus(); } }, [editing]); const toggleEdit = () => { setEditing(!editing); form.setFieldsValue({ [dataIndex]: record[dataIndex] }); }; const save = async e => { try { const values = await form.validateFields(); toggleEdit(); handleSave({ ...record, ...values }); } catch (errInfo) { console.log('Save failed:', errInfo); } }; let childNode = children; if (editable) { childNode = editing ? ( ) : (
{children}
); } return {childNode}; }; class EditableTable extends React.Component { constructor(props) { super(props); this.columns = [ { title: 'name', dataIndex: 'name', width: '30%', editable: true, }, { title: 'age', dataIndex: 'age', }, { title: 'address', dataIndex: 'address', }, { title: 'operation', dataIndex: 'operation', render: (text, record) => this.state.dataSource.length >= 1 ? ( this.handleDelete(record.key)}> Delete ) : null, }, ]; this.state = { dataSource: [ { key: '0', name: 'Edward King 0', age: '32', address: 'London, Park Lane no. 0', }, { key: '1', name: 'Edward King 1', age: '32', address: 'London, Park Lane no. 1', }, ], count: 2, }; } handleDelete = key => { const dataSource = [...this.state.dataSource]; this.setState({ dataSource: dataSource.filter(item => item.key !== key) }); }; handleAdd = () => { const { count, dataSource } = this.state; const newData = { key: count, name: `Edward King ${count}`, age: 32, address: `London, Park Lane no. ${count}`, }; this.setState({ dataSource: [...dataSource, newData], count: count + 1, }); }; handleSave = row => { const newData = [...this.state.dataSource]; const index = newData.findIndex(item => row.key === item.key); const item = newData[index]; newData.splice(index, 1, { ...item, ...row, }); this.setState({ dataSource: newData }); }; render() { const { dataSource } = this.state; const components = { body: { row: EditableRow, cell: EditableCell, }, }; const columns = this.columns.map(col => { if (!col.editable) { return col; } return { ...col, onCell: record => ({ record, editable: col.editable, dataIndex: col.dataIndex, title: col.title, handleSave: this.handleSave, }), }; }); return (
'editable-row'} bordered dataSource={dataSource} columns={columns} /> ); } } ReactDOM.render(, mountNode); ``` ```css .editable-cell { position: relative; } .editable-cell-value-wrap { padding: 5px 12px; cursor: pointer; } .editable-row:hover .editable-cell-value-wrap { border: 1px solid #d9d9d9; border-radius: 4px; padding: 4px 11px; } [data-theme='dark'] .editable-row:hover .editable-cell-value-wrap { border: 1px solid #434343; } ```