ant design v4笔记
前言
最近在使用ant design pro的时候,遇到很多问题,也花费了不少时间,为了防止后续遗忘,特意记录一下,也算是帮大家踩坑了。
使用哪个版本
目前最新的是ant design pro v4的版本,但是网上大部分的教程还是v3甚至还要早的,v4和v3相比还是很多地方不一样的,大部分实例已经变成react hook的形式,也就是函数组件的形式,在v3的时候大多数还是使用的class。
所以如果是新手学习起步的,建议直接使用v4,学最好学最新的东西,如果是在修改老的项目,优先选用当前的版本的代码,因为改起来还是挺麻烦的,亲身经历。
子组件修改父组件的state
目前有两种情况:
1.使用class的有状态组件进行传值(class那种)
2.使用react hook的函数组件进行传值(function的那种)
下面一一展开
首先是 class 形式函数组件,
import React from "react";
import {Input} from "antd";
export default class Parent extends React.Component{
  constructor(props) {
    super(props);
    this.state ={value:""}
  }
  handleChange = (newValue) =>{
    console.log("父组件获取新值",newValue);
    this.setState({
      value:newValue
    });
  }
  render() {
    return  ;
  }
}
class MyInput extends React.Component{
  handleChange =(event)=>{
    // 关键部分这里的this.props会调用父组件的方法,进而修改父类的state
    this.props.onChange(event.target.value)
  }
  render() {
    return 
  }
}
这个例子是在父组件中引入一个包含Input的子组件,子组件的Input组件值发生改变的时候父组件的也受影响发生改变。
因为setState是异步的所以在使用的时候,尤其涉及到count计算之类的时候,最好使用下面的形式
   this.setState((preState)=>{
      return({count:preState.count+1})
    });
   // preState是历史的状态
同样的功能使用函数组件的形式实现
import {useState} from "react"
import {Input} from "antd";
export default function Parent() {
  // useState是React Hook中的 它的参数含义如下
  // 第一个值;value 相当于class里面的this.state={value:""}
  // 第二个值:一般约定是setValue这样的形式,它的作用相当于
  // this.setState({value:"新的值"})
  const [value,setValue] = useState()
  function handleChange(newValue){
    console.log("父组件获取新值",newValue);
    setValue(newValue)
  }
  return value={value} onChange ={handleChange} />
}
function MyInput(props){
  function handleChange(event) {
    props.onChange(event.target.value)
  }
  return value={props.value} onChange={handleChange}/>
}
 坑人的Form
从v3升级到v4最坑的就是Form,因为我的项目使用的class 的形式所以,这里没有使用React Hook的形式去写,但是官网上v4使用的基本上都是函数组件的形式,在v3中使用Form的时候,需要使用Form.Create包裹下组件才能使用一些值,但是在V4中是不能使用Form.Create的,所以在这期间我调查了好久,最后算是解决了,我用的例子就是官网那个可编辑表格,参考v3和官网的迁移指南最后修改完成
/*eslint-disable */
import {Form, Input, InputNumber, Popconfirm, Table} from 'antd';
import React from "react";
import {FormInstance} from "antd/es/form";
const originData: any = [];
for (let i = 0; i < 100; i+=1) {
  originData.push({
    key: i.toString(),
    name: `Edrward ${i}`,
    age: 32,
    address: `London Park no. ${i}`,
  });
}
class EditableCell extends React.Component<any, any> {
  getInput = () => {
    if (this.props.inputType === 'number') {
      return  ;
    }
    return ;
  };
  render() {
    const {
      editing,
      dataIndex,
      title,
      inputType,
      record,
      index,
      children,
      ...restProps
    } = this.props
    return (
      
        {editing ? (
          // 这个地方不用再使用getFieldDecorator(这破玩意至今拼不对)
          // 这个name写了之后 初始值就要在Form上设置了 initialValues
          0}} rules={[{
            required: true,
            message: `Please Input ${title}!`,
          }]}>
            {this.getInput()}
           
        ) : (
          children
        )}
      
    );
  }
}
class EditableTable extends React.Component<any, any> {
  formRef = React.createRef();
  // React Hook使用的 useForm,这里使用React.createRef代替
  isEditing = record => record.key === this.props.state.editingKey;
  edit(record: any) {
    // 这里需要通过setFieldsValue
    this.formRef?.current?.setFieldsValue({
      name: '',
      age: '',
      address: '',
      ...record,
    });
    // 调用父组件的方法开始传值
    this.props.handleEdit(record)
  };
  cancel = () => {
    this.props.handleCancel()
  };
  save(key: any) {
    // getFieldsValue获取当前所选的行的值
    const row = this.formRef?.current?.getFieldsValue();
    const newData = [...this.props.state.data];
    // 根据索引匹配当前的数据
    const index = newData.findIndex((item) => key === item.key);
    if (index > -1) {
      const item = newData[index];
      newData.splice(index, 1, {...item, ...row});
    } else {
      newData.push(row);
    }
    this.props.handleSave(newData)
  };
  render() {
    const components = {
      //修改table该属性默认行为
      body: {
        cell: EditableCell,
      },
    };
    const columns = [
      {
        title: 'name',
        dataIndex: 'name',
        width: '25%',
        editable: true,
      },
      {
        title: 'age',
        dataIndex: 'age',
        width: '15%',
        editable: true,
      },
      {
        title: 'address',
        dataIndex: 'address',
        width: '40%',
        editable: true,
      },
      {
        title: 'operation',
        dataIndex: 'operation',
        render: (text, record) => {
          const {editingKey} = this.props.state;
          const editable = this.isEditing(record);
          return editable ? (
            
                          onClick={() => this.save(record.key)}
              style={{
                marginRight: 8,
              }}
            >
              Save
            
              "Sure to cancel?"  onConfirm={() => this.cancel()}>
                Cancel
              
          
          ) : (
            ''} onClick={() => this.edit(record)}>
              Edit
            
          );
        },
      },
    ];
    const mergedColumns = columns?.map(col => {
      if (!col.editable) {
        return col;
      }
      return {
        ...col,
        onCell: record => ({
          record,
          inputType: col.dataIndex === 'age' ? 'number' : 'text',
          dataIndex: col.dataIndex,
          title: col.title,
          editing: this.isEditing(record),
        }),
      };
    });
    return (
      // ref属性是必须加的,这样子组件才能使用form的属性
       