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实现可增删改表格的资料请关注我们其它相关文章!

(0)

相关推荐

  • React+Antd+Redux实现待办事件的方法

    之前也是写过一篇关于Redux的文章,来简单理解一下Redux,以及该如何使用.今天我就来分享一个也是入门级别的,React+Redux+antd来实现简单的待办事件.同时也讲讲自己对Redux的理解.先来看一张图吧: 我们简单的比喻来让我们更加好的理解Redux,我们这样比喻(图书馆借书): 1.React Component:借书人 2.Action Creators:你要说你要借书这句话,肯定要说话吧,就是一句话:我要借书 3.Store:图书馆管理员 4.Reducer:图书馆管理员肯定

  • react实现antd线上主题动态切换功能

    demo 框架选择: create-react-app + mobx + webpack5 + antdesign 说明 由于最近公司有多个主题的共存性,所以需要实现线上主题切换的功能,所以本文主要描述的是基于create-react-app之上的主题切换. CSS切换 有考虑过根据用户选择的主题在切换的时候选择加载页面css文件的区分方案,但是考虑到这种形式需要在页面切换的时候去reload,因为htmlDOM是在css与JS的结合产物,用户体验不是很好. Less切换 单纯引入所有的less

  • 详解对于React结合Antd的Form组件实现登录功能

    一.React 结合 Antd 实现登录功能 引入所需的 Antd 组件,代码如下所示: import { Form, Icon, Input, Button, message } from 'antd' 在 Login.jsx 中,创建一个 Login 组件.当对外暴露组件时,需要使用 Form 组件进行包装,包装 Form 组件生成一个新的组件 Form(Login),同时新组件会向 Form 组件传递一个强大的对象属性 form,这样就可以取到 Form 表单的值,这也是高阶组件和高阶函数

  • react使用antd表单赋值,用于修改弹框的操作

    1.使用getFieldDecorator的initialValue 2.在state里定义一个变量存表格的数据 3.给打开弹框的方法传个record 4.把表格里的值存到state 5.把在state里存的值传给弹框 6.获取传过来的值 7.在取消方法和修改成功后中给赋空值,要不然,点击添加的方法表单里面会有值 7.OK 补充知识:react中使用antd的表单重置数据 resetFields 重置一组输入控件的值(为 initialValue)与状态,如不传入参数,则重置所有组件 Funct

  • 在react-antd中弹出层form内容传递给父组件的操作

    我就废话不多说了,大家还是直接看代码吧~ 子组件: // jshint esversion:6 import React, { Component } from 'react'; import { Form, Input} from 'antd'; const FormItem = Form.Item; class Forms extends Component{ getItemsValue = ()=>{ //3.自定义方法,用来传递数据(需要在父组件中调用获取数据) const values

  • create-react-app使用antd按需加载的样式无效问题的解决

    官网给出的按需加载解决方案,先安装 babel-plugin-import 因为antd默认引入样式是less,所以需要手动配置为CSS,配置方法如下: 第一种方法:在package.json中配置,这种方法成功的前提是webpack里query下配置babelrc:true, 这样就会使用babelrc文件中的配置 "babel": { "presets": [ "react-app" ], "plugins": [ [ &

  • react+antd 递归实现树状目录操作

    1.写在前面 作为前端小白的我一直对算法和数据结构浅尝辄止,哝,吃亏了.使用多次递归实现数据格式化后将数据进行树状展示的目的,分享一下我这次挠头的经历~ 2.数据 后台传过来的数据大概是这样的 { "data":[ { "id":1, "name":"一级节点", "parentId":0, "isValid":true, "canAddChild":true, &q

  • 在react项目中使用antd的form组件,动态设置input框的值

    问题: 创建账号时,输入账号后不搜索直接保存,提示查询后,再点搜索就不能搜索这个账号了 原因: 点击保存之后,对表单进行了验证,导致之后请求的数据无法在更新到input框中,也就是说即使在state中有值,也不会更新initialValue值,就导致搜索后的值不能正确填入input中,表单也就提交不了. 解决办法: 不使用initialValue设置动态更新的值,而是使用 this.props.form.setFieldValue({name:data}); 用于动态更新值,就可以解决了. if

  • react antd表格中渲染一张或多张图片的实例

    使用antd table中显示一张图片,代码如下: const columns = [ { title: "姓名", dataIndex: "name", width: 100 , // table列定宽 可不设 fixed: "left" // 固定列的位置 }, { title: "联系电话", width: 150, dataIndex: "phone" }, { title:"显示一张图片

  • React antd tabs切换造成子组件重复刷新

    描述: Tabs组件在来回切换的过程中,造成TabPane中包含的相同子组件重复渲染,例如: <Tabs activeKey={tabActiveKey} onChange={(key: string) => this.changeTab(key)} type="card" > <TabPane tab={"对外授权"} key="/authed-by-me"> <AuthedCollections colle

  • 解决React在安装antd之后出现的Can't resolve './locale'问题(推荐)

    React在安装antd之后出现的Can't resolve './locale'问题,是因为moment在2.2之后的版本都有问题,而react默认使用了最新的moment,但是在moment@2.18.1中是没有问题的. 解决方案就是配置webpack的alias,将所有的 moment 路径引用导入到 moment@2.18.1 操作步骤 安装moment 依赖 npm install moment@2.18.1 在react项目中使用yarn eject暴露config文件.如果没有安装

随机推荐