「这是我参与2022首次更文挑战的第34天,活动详情查看:2022首次更文挑战」。
写在前面
- 前面三篇文章,我们一步一步完善 createForm 的功能,逐步实现了用户数据输入的托管,输入数据的统一管理以及数据的校验
- 前面也提到了,createForm 应该支持的功能有一下三点
- 接管用户数据的输入,并统一管理输入的数据
- 校验校验数据的正确性
- 提交数据
- 今天这篇文章,我们将继续完善 createForm 中的数据提交的功能
提交数据
- 这里说的提交数据,指的就是从 createForm 所集中管理的数据中,获取数据
- 其实也很简单,下面是代码实现
getFieldsValue = () => {
return this.state;
};
// 设置时就是传的一个对象
setFieldsValue = (newValue) => {
this.setState(newValue);
};
- getFieldsValue 就是获取数据的方法,直接返回 this.state 即可
- 与 getFieldsValue 相对的是 setFieldsValue,用于设置数据
- 到这里,可能有读者好奇了,不是已经托管了数据的输入吗,还要这个 setFieldsValue 干嘛
- 有了 setFieldsValue,我们就可以通过代码去设置数据了,比如在组件挂载时,设置一个默认值
- 写好了这两个方法,我们就需要将其暴露给外部,也就是添加到 getForm 方法返回的对象中
getForm = () => ({
getFieldDecorator: this.getFieldDecorator,
getFieldsValue: this.getFieldsValue,
setFieldsValue: this.setFieldsValue,
validateFields: this.validateFields,
});
render() {
const { ...otherProps } = this.props;
const form = this.getForm();
return <Com {...otherProps} form={form} />;
}
验证 createForm 的可行性
- 下面看下完整 demo 的代码
import React, { Component } from "react";
// import { createForm } from "rc-form";
import { createForm } from "./components/createForm";
import { Input } from "./components/Input";
const rules = {
user: { required: true, message: "请输入用户名!" },
pwd: { required: true, message: "请输入密码!" },
};
@createForm
export class MyCreateFormDemo extends Component {
submit = () => {
const { form } = this.props;
const allValue = form.getFieldsValue();
console.log(allValue);
form.validateFields(({ err, value }) => {
if (err) {
console.log("error:", err);
} else {
console.log("success", value);
}
});
};
renderField = (type) => {
const { form } = this.props;
return form.getFieldDecorator(type, { rules: [rules[type]] })(
<Input placeholder={type} />
);
};
componentDidMount() {
const { form } = this.props;
form.setFieldsValue({ user: "defaultVal" });
}
render() {
const { form } = this.props;
console.log(form);
return (
<div>
{this.renderField("user")}
{this.renderField("pwd")}
<button onClick={this.submit}>提交</button>
</div>
);
}
}
- 我们实现了一个 submit 方法,用于 MyCreateFormDemo 组件的数据提交
- 在其内部,可以通过 form.getFieldsValue 获取所有输入到 MyCreateFormDemo 组件中的数据
- 我们只需要调用 form.validateFields 进行数据校验,然后根据校验结果,执行相应操作即可
- 下面是页面功能的运行情况:
- 没有填写数据时,点击提交按钮
- 填写一个数据时,点击提交按钮
- 填写所有数据时,点击提交按钮
小结
- 至此,我们的最简版本的 createForm 已经实现完成了
- 怎么样,读者小伙伴们是不是感觉很 esay
- 但是它的设计其实有个缺点,rc-form 是通过高阶组件来实现接管用户数据的输入,并统一管理输入的数据的
- 也就意味着,所有的
数据输入组件经过 getFieldDecorator 方法转换之后,都使用了 createForm 返回的组件的 state - 一旦有某一个
数据输入组件开始接收数据,那么最上层的管理数据的组件的 state 就会发生改变,从而引起其进行更新 - 由于我们自己的 form 组件通过高阶组件的转换之后,接收了来自父组件,也就是最上层管理数据的组件的 props,所以我们自己 form 组件的也会发生更新
- 仅仅是某一个
数据输入组件发生了更新,却会导致整个 form 组件都发生更新,这就造成了性能的浪费了
- 也就意味着,所有的
- 因此,antd4 则重构了 form 组件,替换 rc-form 为 rc-field-form
- rc-field-form 没有使用高阶组件,而是使用 hooks + contenxt 的方式,很好的解决了上面说的问题
- 下篇文章,我们将继续手写 rc-field-form
最后
- 今天的分享就到这里了,欢迎大家在评论区里面进行讨论 👏。
- 如果觉得文章写的不错的话,希望大家不要吝惜点赞,大家的鼓励是我分享的最大动力 🥰