最近写了一个小东西,模仿自己原先用vue写的项目改成react语法。写了一个可编辑的表格,期间磕磕碰碰的,打算把bug记录下。先把效果图和代码贴上去,主要用的是react+antd
import React, { useState }from 'react'
import { Row,Col,Card, Table, Tag, Divider, Modal, Button } from 'antd';
import ModalData from './model'
const App = (props) => {
console.log(props,'----')
const [isModalVisible, setIsModalVisible] = useState(false);
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: text => <a>{text}</a>,
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
{
title: 'Tags',
key: 'tags',
dataIndex: 'tags',
render: tags => (
<label>
{tags.map(tag => {
let color = tag.length > 5 ? 'geekblue' : 'green';
if (tag === 'loser') {
color = 'volcano';
}
return (
<Tag color={color} key={tag}>
{tag.toUpperCase()}
</Tag>
);
})}
</label>
),
},
{
title: 'Action',
key: 'action',
align:'center',
render: (record) => (
<label>
<a onClick={() => showModal(record)}>编辑</a>
<Divider type="vertical" />
{/* */}
<a onClick={()=>showModal(record)} > 删除</a>
</label>
),
},
];
const data = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer'],
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
tags: ['loser'],
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
tags: ['cool', 'teacher'],
}
];
const showModal = (row) => {
setIsModalVisible(true);
};
const handleCancel = () => {
setIsModalVisible(false);
}
const handleOk = (form={},data) => {
setIsModalVisible(false);
console.log(form,data,'pp---')
}
return (
<label>
<Row gutter={16} className="gutter-row">
<Col md={24}>
<Card title="基本表格+简单弹框" bordered={false}>
<Table columns={columns} dataSource={data} />
</Card>
</Col>
</Row>
{isModalVisible && <ModalData close={()=>{
handleCancel()
}} saveOk={(form,data)=>{ handleOk(form,data) }}/>}
{/* {isModalVisible && } */}
</label>
);
};
const la = '111'
export default () => (
<App/>
)
import React from 'react'
import Basic from './modules/base'
import EditTableData from './modules/editTableData'
import { Modal, Tabs, Spin } from "antd";
export default class ModalData extends React.Component{
constructor(){
super()
this.state = {
isModalVisible:true,
currentTab:'basicColumns',
tableData:[]
}
}
componentWillMount(){
this.setState({
isModalVisible:this.props.isModalVisible
})
this.basicColumns = [
{title:'操作类型',editable:true,dataIndex:'name'},
{title:'名称',editable:true,dataIndex:'age'},
{title:'描述',editable:true,dataIndex:'address'}
]
this.associationColumns = [
{title:'前置操作',editable:true,dataIndex:'name'},
{title:'关联权限',editable:true,dataIndex:'age'},
{title:'关联操作',editable:true,dataIndex:'address'}
]
this.dataViewColumns = [
{title:'字段',editable:true,dataIndex:'name'},
{title:'描述',editable:true,dataIndex:'address'}
]
}
componentWillUpdate(){
console.log(22)
}
componentDidMount(){
console.log(11)
}
handleOk = () => {
// console.log(this.tabData,'this.formRefThree.props')
const form = this.formRef.props.form;
form.validateFields((err, fieldsValue) => {
if (!err) {
console.log(this.tabData,'pp---00---');
this.props.saveOk(fieldsValue,this.tabData)
}
});
}
saveTable(data){
console.log(data,this.state.currentTab,'data---')
this.tabData = {
[this.state.currentTab]:data
}
}
changeTab(key){
console.log(key,'key---')
this.setState({
currentTab:key
})
}
render(){
return (
<Modal
title="编辑"
width={650}
destroyOnClose
visible
onOk={ () => this.handleOk() }
onCancel={ () => this.props.close()}
>
<Tabs onChange={(key)=>this.changeTab(key)} >
<Tabs.TabPane tab="基本信息" key="basicColumns">
<span>
<Basic wrappedComponentRef={(form) => this.formRef = form}/>
<EditTableData basicColumns={this.basicColumns} saveTable={(data)=>this.saveTable(data)}/>
</span>
</Tabs.TabPane>
<Tabs.TabPane tab="关联权限" key="associationColumns">
<EditTableData associationColumns={this.associationColumns} saveTable={(data)=>this.saveTable(data)}/>
</Tabs.TabPane>
<Tabs.TabPane tab="数据视图" key="dataViewColumns">
<EditTableData dataViewColumns={this.dataViewColumns} saveTable={(data)=>this.saveTable(data)}/>
</Tabs.TabPane>
</Tabs>
</Modal>
)
}
}
import React from 'react'
import { Form, Input, Select, Radio } from 'antd';
const { Option } = Select;
// const Basic = (props) => {
class Basic extends React.Component{
formRef = React.createRef();
// const [form] = Form.useForm();
onGenderChange(value){
switch (value) {
case 'male':
this.props.form.setFieldsValue({
note: 'Hi, man!',
});
return;
case 'female':
this.props.form.setFieldsValue({
note: 'Hi, lady!',
});
return;
case 'other':
this.props.form.setFieldsValue({
note: 'Hi there!',
});
return;
}
}
onFinish(values){
console.log(values);
console.log(this.props.form.getFieldsValue,'09900--')
}
render(){
console.log(this.props.form.getFieldValue('gender'),'990----')
const { form } = this.props;
const { getFieldDecorator, getFieldValue} = form;
return (
<div>
<Form ref={this.formRef} layout="inline" name="control-hooks" onFinish={this.onFinish.bind(this)}>
<Form.Item label="权限标识" required>
{getFieldDecorator("note")(<Input placeholder="请输入"/>)}
</Form.Item>
<Form.Item label="权限名称" required>
{getFieldDecorator("name")(<Input placeholder="请输入"/>)}
</Form.Item>
<Form.Item label="requiredMark" name="状态" required>
{getFieldDecorator("requiredMark")(
<Radio.Group>
<Radio.Button value="optional">启用</Radio.Button>
<Radio.Button value="disabled">禁用</Radio.Button>
</Radio.Group>
)}
</Form.Item>
<Form.Item name="gender" label="分类" required>
{getFieldDecorator("gender")(
<Select style={{width: '250px'}} placeholder="请选择" onChange={this.onGenderChange.bind(this)} allowClear >
<Option value="male">api借口</Option>
<Option value="female">租户</Option>
<Option value="other">系统</Option>
</Select>
)}
</Form.Item>
{getFieldValue('gender') == 'other' && <Form.Item name="customizeGender" label="备注">
{getFieldDecorator("customizeGender")(<Input />)}
</Form.Item>}
</Form>
</div>
)
}
}
export default Form.create()(Basic)
import React, { useState } from 'react';
import { Table, Input, InputNumber,Divider, Popconfirm, Form, Typography } from 'antd';
import {PlusSquareOutlined} from '@ant-design/icons';
const { Provider, Consumer } = React.createContext()//组件之间传值
const originData = [];
for (let i = 0; i < 5; i++) {
originData.push({
key: i.toString(),
name: `Edrward ${i}`,
age: 32,
address: `London Park no. ${i}`,
});
}
class EditableCell extends React.Component{
renderCell = ({getFieldDecorator}) => {
const {
editing, dataIndex, title, Inputs, record, index, children, ...restProps
} = this.props
return (
<td {...restProps}>
{editing ? (
<Form.Item style={{ margin: 0, }} >
{getFieldDecorator(dataIndex,{
rules: [{
required: true,
message: '请输入'
}],
initialValue: record[dataIndex]
})(
<Inputs />
)}
</Form.Item>
) : (
children
)}
</td>
);
}
render(){
return <Consumer>{this.renderCell}</Consumer>
}
}
class EditTableData extends React.Component{
constructor(props){
super(props)
this.state = {
data:originData,
editingKey:''
}
}
// 判断是否可编辑
isEditing = record => record.key == this.state.editingKey
// 初始化
init(){
console.log(this.props,'pp--')
const data = this.props.basicColumns || this.props.dataViewColumns || this.props.associationColumns || []
this.columns = [
...data,
{
title: ()=>{
return <span>操作<Divider type="vertical" /><PlusSquareOutlined style={{color:"#333"}} onClick={()=>this.addColumns()}/></span>
},
width:'20%',
dataIndex: 'operation',
render: (_, record) => {
const { editingKey } = this.state
const editable = this.isEditing(record);
return editable ? (
<span>
<Consumer>
{
form => (
<a onClick={() => this.save(form,record.key)} >
保存
</a>)
}
</Consumer>
<Divider type="vertical" />
<Popconfirm okText="确认" cancelText="取消" title="是否确定取消?" onConfirm={this.cancel}>
<a>取消</a>
</Popconfirm>
</span>
) : (
<span>
<a disabled={editingKey != ''} onClick={()=>this.edit(record.key)}>编辑</a>
<Divider type="vertical" />
<Popconfirm okText="确认" cancelText="取消" title="是否确定取消?" onConfirm={()=>this.delete(record.key)}>
<a>删除</a>
</Popconfirm>
</span>
);
},
},
];
}
// 添加
addColumns = () => {
const newData = [...this.state.data]
newData.push({
key: newData.length,
name: ``,
age: '',
address: ``
})
this.setState({
data:newData
})
}
// 编辑
edit = (key) => {
this.setState({
editingKey:key
})
}
// 删除
delete = (key) => {
const newData = [...this.state.data]
const index = newData.findIndex(item=>item.key == key)
newData.splice(index,1)
this.setState({
data:newData
})
}
// 保存
save = (form,key) => {
form.validateFields((error,row)=>{
if(error){
return
}
const newData = [...this.state.data]
const index = newData.findIndex(item=>item.key == key)
if(index > -1){
const item = newData[index]
newData.splice(index,1,{
...item,...row
})
}
this.setState({
editingKey:'',
data:newData
})
this.props.saveTable(newData)
})
}
// 取消
cancel = () => {
this.setState({
editingKey: ''
})
}
render(){
this.init()
console.log(this.columns,'columns')
const columns = this.columns.map(col => {
if(!col.editable){
return col
}
return {
...col,
onCell:record => ({
record,
Inputs:Input,
dataIndex:col.dataIndex,
title:col.title,
editing:this.isEditing(record)
})
}
})
return (
<Provider value={this.props.form}>
<Table bordered style={{marginTop:'30px'}} components={{
body:{
cell:EditableCell
}
}} columns={columns} dataSource={this.state.data} pagination={false}/>
</Provider>
)
}
}
export default Form.create()(EditTableData)