Ant Design - Form

遇见的问题:将form组件提取出来做一个单独的组件,然后在父组件中点击提交的时候,可以获得子组件中form表单的值。
在解决的过程中,有两种方法,一种就是简单直接获取子组件的form表单的值。另一种比较复杂,下面再细说。
第一种方法比较简单。最主要的就是 wrappedComponentRef 这个属性,相当于取得form的整个dom。


// 父组件
handleSubmit = (e) => {
    e.preventDefault();
	this.basicform.props.form.validateFieldsAndScroll((err, values) => {
      if (err) {
        return;
      }
    }
}

render() {
  return (
	 <Card title="基本信息" className="project-edit">
	   <BasicForm
	    wrappedComponentRef={(form) => {
	       this.basicform = form;
	     }}
	   />
	 </Card>
  )
}
 // 子组件
class BasicForm extends PureComponent {

render() {
   const {
     form: { getFieldDecorator },
     data
   } = this.props;
   
   return (
	 <Form
	  hideRequiredMark
	  layout="vertical"
	  style={{ marginTop: 8 }}
	>
	  <FormItem label="姓名">
	    {getFieldDecorator('name', {
	      initialValue: data.name
	    })(<Input placeholder="请输入姓名" />)}
	  </FormItem>
	  ...
	</Form>
   )
  }
}
export default Form.create()(BasicForm);

第一种方法的大致的步骤就是这样了。大部分情况下用第一种方法就好,第二种方法可以作了解。第二种方法不是用this.basicform.props.form 取其form表单数据,是用form的原生方法onChange。

// 父组件
handleSubmit = (e) => {
    e.preventDefault();
	this.props.form.validateFieldsAndScroll((err, values) => {
      if (err) {
        return;
      }
      console.log(values); // {basicForm:{...} }
    }
}

render() {
  return (
	 <Card title="基本信息" className="project-edit">
	 {getFieldDecorator('basicForm', {
	   <BasicForm />
	 })}
	 </Card>
  )
}

// 子组件
class BasicForm extends PureComponent {

handleChange = () => {
    const { form, onChange } = this.props;
    setTimeout(() => {
      form.validateFieldsAndScroll((err, values) => {
        if (err) {
          return;
        }
        onChange(values);
      });
    }, 0);
  }

render() {
   const {
     form: { getFieldDecorator },
     data
   } = this.props;
   
   return (
	 <Form
	  hideRequiredMark
	  layout="vertical"
	  style={{ marginTop: 8 }}
	>
	  <FormItem label="姓名">
	    {getFieldDecorator('name', {
	      initialValue: data.name
	    })(<Input placeholder="请输入姓名" onChange={this.handleChange} />)}
	  </FormItem>
	  ...
	</Form>
   )
  }
}
export default Form.create()(BasicForm);

第二种方法这里涉及几个知识点需要先了解一下。

经过 getFieldDecorator 包装的控件,表单控件会自动添加 value(或 valuePropName 指定的其他属性) onChange(或 trigger 指定的其他属性),数据同步将被 Form 接管,这会导致以下结果:

  1. 你不再需要也不应该用 onChange 来做同步,但还是可以继续监听 onChange 等事件。
  2. 你不能用控件的 value defaultValue 等属性来设置表单域的值,默认值可以用 getFieldDecorator 里的 initialValue。
  3. 你不应该用 setState,可以使用 this.props.form.setFieldsValue 来动态改变表单值。

如果你需要通过监听 onChange 等事件来改变value的值,你可以参考这个方法。

值得注意的是,这里 onChange 有个坑,通过onChange来获取表单数据的时候发现此时通过表单方法获取的值还没有更新,还是上一次更新的表单的值,我们就无法实时获取表单的正确数据,所以这里添了 setTimeout 这个延时方法,这样就可以在 onChange 方法中获取最新的表单数据。

另一个 onChange() 和上面讲的onChange() 就不是一件事了。form数据更新必须要执行 props 中的 onChange 方法,这样父组件获得的form数据才是最新的,如果一直不执行 onChange 方法,那么父组件就无法获得子组件的表单数据。

参考链接:
http://ju.outofmemory.cn/entry/348216

猜你喜欢

转载自blog.csdn.net/kelly0721/article/details/87382909