首页 > 编程语言 > React+Antd 实现可增删改表格的示例
2021
04-07

React+Antd 实现可增删改表格的示例

最近写了一个小东西,模仿自己原先用vue写的项目改成react语法。写了一个可编辑的表格,期间磕磕碰碰的,打算把bug记录下。先把效果图和代码贴上去,主要用的是react+antd

table表格,点击编辑,打开弹窗,弹窗内是tab切换显示不同的form表单+可编辑表格,表格内操作栏"+",表格内新增一行可编辑的数据,编辑,保存,删除这些操作就不细说也不贴效果图了

Table/index.js

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" />
     {/* <Button onClick={()=>showModal(record)} > 删除</Button> */}
     <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 && <ModalData />} */}
  </label>
 );
};
const la = '111'
export default () => (
 <App/>
)

Table/model/index.js

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>
  )
 }
}

Table/model/modules/base.js

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)

Table/model/modules/editTable.js

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)

以上就是React+Antd实现可增删改表格的示例的详细内容,更多关于React+Antd实现可增删改表格的资料请关注自学编程网其它相关文章!

编程技巧