【React+Antd】可编辑表格

复制代码
import React, { useContext, useState, useEffect, useRef } from "react";
import { Table, Input, Button, Popconfirm, Form } from "antd";

const EditableContext = React.createContext(null);
const EditableRow=(props)=> {//编辑表格行
  let [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 })=>{//编辑表格单元格
  let inputRef = useRef(null);
  const [editing, setEditing] = useState(false); //定义编辑状态
  const form = useContext(EditableContext);

  useEffect(() => {//监听编辑状态值的变化
    if (editing) {//如果开启编辑状态
      inputRef.current.focus(); //input输入框聚焦
    }
  }, [editing]);

  function toggleEdit() {//切换编辑状态
    setEditing(!editing);
    form.setFieldsValue({//将表格中的值赋值到表单中
      // name:Easdf
      [dataIndex]: record[dataIndex],
    });
  }

  async function save() {//保存事件
    try {
      const values = await form.validateFields();//获取表单中的数据
      toggleEdit();//切换编辑状态
      handleSave({ ...record, ...values });//调用保存方法
    } catch (errInfo) {
      console.log("保存失败:", errInfo);
    }
  }

  let childNode = children;
  if (editable) {//如果开启了表格编辑属性
    // 是否开启了编辑状态 (开启:显示输入框 关闭:显示div)
    childNode = editing ? (
      <Form.Item
        name={dataIndex}
        rules={[
          {
            required: true,
            message: `${title}是必填的.`,
          },
        ]}
      >
        <Input ref={inputRef} onPressEnter={save} onBlur={save} />
      </Form.Item>
    ) : (
      <div onClick={toggleEdit}>{children}</div>
    );
  }
  return <td {...restProps}>{childNode}</td>;
}
export default  App=()=> {
  let tableColumns = [//定义表格头
    {
      title: "姓名",
      dataIndex: "name",
      with: "30%",
      editable: true,
    },
    {
      title: "年龄",
      dataIndex: "age",
    },
    {
      title: "地址",
      dataIndex: "address",
    }
  ];
  let [tableData, setTableData] = useState([//定义表格数据
    {
      key: "0",
      name: "Edward King 0",
      age: "32",
      address: "London, Park Lane no. 0",
    },
    {
      key: "1",
      name: "Edward King 1",
      age: "32",
      address: "London, Park Lane no. 1",
    },
  ]);

  tableColumns = tableColumns.map((item) => {//遍历表格头数组
    if (item.editable) {//如果表格头列开启了编辑属性
      return {
        ...item,
        onCell: (record) => {
          return {
            record: record,
            editable: item.editable,
            dataIndex: item.dataIndex,
            title: item.title,
            handleSave: (row) => {//这个方法可以获取到行编辑之后的数据
              let findEditIndex = tableData.findIndex((item) => {//找到编辑行的索引
                return item.key === row.key;
              });
              let findEditObj = tableData.find((item) => {//找到编辑行的数据对象
                return item.key === row.key;
              });
              tableData.splice(findEditIndex, 1, { ...findEditObj, ...row });//将最新的数据更新到表格数据中
              setTableData([...tableData]);//设置表格数据
            },
          };
        },
      };
    } else {
      return item;
    }
  });

  return (
    <div>
      <Table
        bordered
        components={{
          body: {
            row: EditableRow,
            cell: EditableCell,
          },
        }}
        columns={tableColumns}
        dataSource={tableData}
      />
    </div>
  );
}
复制代码

 

posted @   维多利亚的巴黎世家  阅读(610)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
点击右上角即可分享
微信分享提示