首先,官网文档上是有可编辑单元格和可编辑行的。我研究了好几遍,也是半知半解,只会用
官网做法
- 有一定的局限性,单元格内只能是输入框(我试了一些别的,不太行)
代码直接照着文档粘贴,只说一下需要改动的地方
table的数据源,我们都是后端获取,所以这里把默认的清空就行。请求接口获取数据源,直接set进去就行
然后记得给 Table 标签添加 rowKey 属性,绑定唯一值
如果想单元格可编辑,记得添加 editable: true,
下面是我自己练习的一个案例
import { Form, Input, Popconfirm, Table, Button } from 'antd'
import React, { useContext, useEffect, useRef, useState } from 'react'
import './Lll.css'
import axios from 'axios'
const EditableContext = React.createContext(null)
const EditableRow = ({ index, ...props }) => {
const [form] = Form.useForm()
return (
<Form form={form} component={false}>
<EditableContext.Provider value={form}>
<tr {...props} />
</EditableContext.Provider>
</Form>
)
}
const EditableCell = ({
title,
editable,
children,
dataIndex,
record,
handleSave,
...restProps
}) => {
const [editing, setEditing] = useState(false)
const inputRef = useRef(null)
const form = useContext(EditableContext)
useEffect(() => {
if (editing) {
inputRef.current.focus()
}
}, [editing])
const toggleEdit = () => {
setEditing(!editing)
form.setFieldsValue({
[dataIndex]: record[dataIndex],
})
}
const save = async () => {
try {
const values = await form.validateFields()
toggleEdit()
handleSave({
...record,
...values,
})
} catch (errInfo) {
console.log('Save failed:', errInfo)
}
}
let childNode = children
if (editable) {
childNode = editing ? (
<Form.Item
style={{
margin: 0,
}}
name={dataIndex}
rules={[
{
required: true,
message: `${title} is required.`,
},
]}
>
<Input ref={inputRef} onPressEnter={save} onBlur={save} />
</Form.Item>
) : (
<div
className="editable-cell-value-wrap"
style={{
paddingRight: 24,
}}
onClick={toggleEdit}
>
{children}
</div>
)
}
return <td {...restProps}>{childNode}</td>
}
const Lll = () => {
const [dataSource, setDataSource] = useState([])
const handleDelete = (key) => {
const newData = dataSource.filter((item) => item.key !== key)
setDataSource(newData)
}
const defaultColumns = [
{
title: '标题',
dataIndex: 'title',
width: '30%',
editable: true,
ellipsis: true,
},
{
title: '分类',
dataIndex: 'tab',
editable: true,
width: '20%',
},
{
title: '浏览量',
dataIndex: 'reply_count',
editable: true,
width: '20%',
},
{
title: 'operation',
dataIndex: 'operation',
render: (_, record) =>
dataSource.length >= 1 ? (
<Popconfirm
title="确定删除吗?"
onConfirm={() => handleDelete(record.key)}
>
<a>删除</a>
</Popconfirm>
) : null,
},
]
const handleSave = (row) => {
const newData = [...dataSource]
const index = newData.findIndex((item) => row.key === item.key)
const item = newData[index]
newData.splice(index, 1, {
...item,
...row,
})
setDataSource(newData)
}
const components = {
body: {
row: EditableRow,
cell: EditableCell,
},
}
const columns = defaultColumns.map((col) => {
if (!col.editable) {
return col
}
return {
...col,
onCell: (record) => ({
record,
editable: col.editable,
dataIndex: col.dataIndex,
title: col.title,
handleSave,
}),
}
})
// 点击收集
const shouji = () => {
console.log('收集到的值为', dataSource)
}
// 初始化操作
useEffect(() => {
axios
.get('https://cnodejs.org/api/v1/topics')
.then((res) => {
setDataSource(res.data.data)
})
.catch((err) => console.log(err))
}, [])
return (
<div>
<Table
components={components}
rowClassName={() => 'editable-row'}
bordered
dataSource={dataSource}
columns={columns}
rowKey={(record) => record.id}
/>
<Button onClick={shouji}>收集值</Button>
</div>
)
}
export default Lll
其他做法
- 主要是用到了数据驱动视图的思想,只要数据变了,视图自然更新。需要什么标签,render里就写什么
- render属性的值是个函数,默认有三个参数,第一个参数是当前行渲染的数据,第二个参数是后端返回给我们的完整的当前行数据,第三个参数是索引
- 加的有校验,不想加校验就把Form相关的去掉就行
import React, { useState } from 'react'
import { Space, Table, Input, Button, DatePicker, Form } from 'antd'
import moment from 'moment'
export default function Mmm() {
const [form] = Form.useForm()
const columns = [
{
title: '标题',
dataIndex: 'title',
key: 'title',
render: (_, record, index) => (
<Form.Item
name={'title' + record.id}
rules={[
{
required: true,
message: '不能为空!',
},
]}
initialValue={record.title}
>
<Input onBlur={(e) => upTitle(e, index)} />
</Form.Item>
),
},
{
title: '时间',
dataIndex: 'time',
key: 'time',
render: (_, record, index) => (
<Form.Item
name={'time' + record.id}
rules={[
{
required: true,
message: '不能为空!',
},
]}
initialValue={moment(record.time, 'YYYY-MM-DD')}
>
<DatePicker onChange={(time) => upTime(time, index)} />
</Form.Item>
),
},
{
title: '操作',
key: 'action',
render: (_, record, index) => (
<Space size="middle">
<Button onClick={() => delItem(index)}>删除</Button>
</Space>
),
},
]
const [data, setData] = useState([
{
id: 0,
title: '标题1',
time: '2023-03-13',
},
{
id: 1,
title: '标题2',
time: '2023-03-14',
},
])
// 标题修改后失焦
const upTitle = (e, index) => {
let newArr = JSON.parse(JSON.stringify(data))
newArr[index].title = e.target.value
setData(newArr)
}
// 时间选择后
const upTime = (time, index) => {
let newArr = JSON.parse(JSON.stringify(data))
newArr[index].time = time?.format('YYYY-MM-DD') || ''
setData(newArr)
}
// 点击删除
const delItem = (index) => {
let newArr = JSON.parse(JSON.stringify(data))
newArr.splice(index, 1)
setData(newArr)
}
// 点击收集数据按钮
const getData = () => {
form.validateFields().then((res) => {
// console.log(res)
console.log('收集到的数据为', data)
})
}
return (
<div>
<Form form={form}>
<Table
columns={columns}
dataSource={data}
rowKey={(record) => record.id}
/>
</Form>
<Button onClick={getData}>收集数据</Button>
</div>
)
}
版权归原作者 小辉吖~ 所有, 如有侵权,请联系我们删除。