antd-Form4.x一个页面中多个表单处理

一、前言

今天开发的时候,发现一个页面的表单其实是两个部分,其中一部分还在另一个页面引用了。这就增加代码量,所以优化下,为了重复使用这里的表单。

如图,需求就是将下面两个表单拆开,可以重复使用,实际两部分可能有很多表单,这里方便起见,只写了三个。

image.png

二、涉及到知识点

  • react hooks
  • antd 4.0(Form)
  • Promise
  • 子父组件传值和父组件调用子组件方法

三、实现方法

具体实现:我放在了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>
  );
}
复制代码

在该文件中,我们引入了两个表单的模版,通过ref属性获取组件,通过props传入父组件的变量。

当我们调用handleCommit的时候,该函数会调用子组件定义好的commitForm的方法来获取表单的数据,获取的数据通过回调函数返回。

因为多个组件存在异步获取的问题,所以这里通过promise.all方法,获取多个表单的内容,然后统一处理。

image.png

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);
复制代码

这个组件是我们定义的表单模版,正常读取后,通过asyncawait获取表单内容,最后再通过commitForm方法,返回给父组件。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享