React+Antd实现可增删改表格

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

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

React+Antd实现可增删改表格_第1张图片
React+Antd实现可增删改表格_第2张图片
React+Antd实现可增删改表格_第3张图片
React+Antd实现可增删改表格_第4张图片
React+Antd实现可增删改表格_第5张图片

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" />
          {/*  */}
          <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/>
)
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,reactjs,es6,javascript)