实现antd中Form、Form.Item组件
初始化项目
使用create-react-app初始化项目后创建MyRcFieldForm文件,代码如下
import React, {
Component, useEffect } from 'react';
import Form, {
Field } from 'rc-field-form';
//import Form, { Field } from './components/my-rc-field-form/';
import Input from './components/Input';
const nameRules = {
required: true, message: '请输入姓名!' };
const passworRules = {
required: true, message: '请输入密码!' };
export default function MyRCFieldForm(props) {
const [form] = Form.useForm();
const onFinish = (val) => {
console.log('onFinish', val); //sy-log
};
// 表单校验失败执行
const onFinishFailed = (val) => {
console.log('onFinishFailed', val); //sy-log
};
useEffect(() => {
console.log('form', form); //sy-log
form.setFieldsValue({
username: 'default' });
}, []);
return (
<div>
<h3>MyRCFieldForm</h3>
<Form form={
form} onFinish={
onFinish} onFinishFailed={
onFinishFailed}>
<Field name='username' rules={
[nameRules]}>
<Input placeholder='input UR Username' />
</Field>
<Field name='password' rules={
[passworRules]}>
<Input placeholder='input UR Password' />
</Field>
<button>Submit</button>
</Form>
</div>
);
}
Input组件代码
import React from 'react';
const Input = (props) => {
return <input {
...props} />;
};
class CustomizeInput extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
const {
value = '', ...otherProps } = this.props;
return (
<div style={
{
padding: 10 }}>
<Input style={
{
outline: 'none' }} value={
value} {
...otherProps} />
</div>
);
}
}
export default CustomizeInput;
上面文件中的Form,Field组件是从rc-field-form
库中引入的,接下来我们要自己实现这两个组件。
原理以及实现思路
让我们先来回顾一下antd4.0中表单组件的使用方法,首先使用Form
组件包裹自组件,给Form
组件可以添加onFinish
,onFieldsChange
等事件,在这些事件中可以监听到表单的改变获取到表单值然后做相应的处理。我们还可以使用Form.useForm
方法获取表单实例,通过该实例中的方法(setFieldsValue,getFieldsValue,validate
)我们可以获取、设置、校验表单值。然后使用Form.Item
组件包裹表单组件,给Form.Item
组件添加上name
,rules
等属性。然后当表单被输入是我们可以获取到表单的内容。
const Demo = () => {
const [form] = Form.useForm();
const handleChange = values => console.log(values);
return (
<Form form={
form} onChange={
handlChange}>
<Form.Item name="usename" >
<Input />
</Form.Item>
</Form>
)
}
实现思路:首先我们需要将表单组件的输入值存储到一个公共的位置 store
,然后,暴露出修改方法给表单组件,当表单组件Input
的 onChange
事件触发后调用修改方法(setFieldsValue
)将新的值更新到store
,然后重新触发组件渲染将视图同步。我们通过Form.useForm
创建store
的实例,然后通过React
中的context
将实例传递给各个Form.Item
组件。在Form.Item
组件中我们需要为表单组件Input
实现onChange
事件,将改变通过context
中的实例方法更新到store
当中,最后重新渲染自己实现视图同步。
搭出Form、Field组件,useForm自定义hook的架子
- context文件
const FormContext = React.createContext();
export default FormContext;
- Form
import FormContext from './context'
const Form = ({
children, form}) => {
return (
<FormContext.Provider value={
form}>
<form>{
children}</form>
</FormContext.Provider>
)
}
- Field
import FormContext <