前言
我是本际云服务器推荐网的小编小本本,今天在开发中发现一个页面的表单其实是两个部分,其中一部分还在另一个页面引用了,导致代码量增加。所以我决定进行优化,为了重复使用这里的表单。

如图,需求就是将下面两个表单拆开,可以重复使用,实际两部分可能有很多表单,这里方便起见,只写了三个。
涉及到知识点
1. React Hooks
2. Antd 4.0(Form)
3. Promise
4. 子父组件传值和父组件调用子组件方法
实现方法
具体实现我放在了 Codesandbox,可以直接打开调试:
1、首先为了充分复用表单组件,那么就要拆分的彻底一点,不能关联太多内容。
2、一个模版表单多带作为一个组件,表单通过 useForm() 创建。
3、在组件外部进行表单提交,分别触发,然后通过 Promise.all 方法获取表单数据。
4、编辑的时候,可以通过 props 将给表单赋值,然后给子组件注册供父组件调用的方法。
具体操作
我们通过 codesandbox 来试验下,这里表单添加的比较少,可以自行增加。
新建 index.js 文件,表单最后显示在这里两个表单模版:templateForm1.js,templateForm2.js,由于这两个文件的内容基本一样,需要根据自己的表单内容定义,所以我们这里写了一个。
<import React, {useRef} from "react";
import {Button, Divider} from "antd";
import TemplateForm1 from "./templateForm1";
import TemplateForm2 from "./templateForm2";
export default function App() {
const template1Ref = useRef();
const template2Ref = useRef();
const formItemLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 10 }
};
const handleCommit = () => {
let template1Data = new Promise((resolve, reject) => {
template1Ref.current.commitForm((value) => {
resolve(value);
});
});
let template2Data = new Promise((resolve, reject) => {
template2Ref.current.commitForm((value) => {
resolve(value);
});
});
Promise.all([template1Data, template2Data]).then((res) => {
console.log("get", res);
});
};
return (
<div className="App">
<Divider orientation="left">内部信息</Divider>
<TemplateForm1 ref={template1Ref} formItemLayout={formItemLayout} />
<Divider orientation="left">外部信息</Divider>
<TemplateForm2 ref={template2Ref} formItemLayout={formItemLayout} />
<Button onClick={handleCommit}>提交</Button>
</div>
);
}></import>
在该文件中,我们引入了两个表单的模版,通过 ref 属性获取组件,通过 props 传入父组件的变量。当我们调用 handleCommit 的时候,该函数会调用子组件定义好的 commitForm 的方法来获取表单的数据,获取的数据通过回调函数返回。因为多个组件存在异步获取的问题,所以这里通过 Promise.all 方法,获取多个表单的内容,然后统一处理。
import React, {useImperativeHandle, forwardRef} from "react";
import {Form, Input} from "antd";
const TemplateForm1 = (props, ref) => {
const { formItemLayout } = props;
const [form] = Form.useForm();
useImperativeHandle(ref, () => ({
commitForm: (cb) => {
handleCommit(cb);
}
}));
const handleCommit = async (cb) => {
try {
const values = await form.validateFields();
cb(values);
} catch (err) {
console.log(err);
}
};
return (
<Form form={form} {...formItemLayout}>
<Form.Item
name="Name"
label="名称"
rules={[{ required: true, message: "请输入名称" }]}
>
<Input placeholder="点输入名称" />
</Form.Item>
</Form>
);
};
export default forwardRef(TemplateForm1);
这个组件是我们定义的表单模版,正常读取后,通过 async 和 await 获取表单内容,最后再通过 commitForm 方法,返回给父组件。
已完成。
原创文章,作者:小编小本本,如若转载,请注明出处:https://www.benjiyun.com/yunzhujiyunwei/vps-yunwei/7403.html
