遇见的问题:将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 接管,这会导致以下结果:
- 你不再需要也不应该用 onChange 来做同步,但还是可以继续监听 onChange 等事件。
- 你不能用控件的 value defaultValue 等属性来设置表单域的值,默认值可以用 getFieldDecorator 里的 initialValue。
- 你不应该用 setState,可以使用 this.props.form.setFieldsValue 来动态改变表单值。
如果你需要通过监听 onChange 等事件来改变value的值,你可以参考这个方法。
值得注意的是,这里 onChange 有个坑,通过onChange来获取表单数据的时候发现此时通过表单方法获取的值还没有更新,还是上一次更新的表单的值,我们就无法实时获取表单的正确数据,所以这里添了 setTimeout 这个延时方法,这样就可以在 onChange 方法中获取最新的表单数据。
另一个 onChange() 和上面讲的onChange() 就不是一件事了。form数据更新必须要执行 props 中的 onChange 方法,这样父组件获得的form数据才是最新的,如果一直不执行 onChange 方法,那么父组件就无法获得子组件的表单数据。