实现一个React From组件

简单模拟 antd 的 form 组件实现。
先看下如何使用:

import React from 'react';
import Form from '../components/Form/From';

//引用高阶组件
@Form.formCreate
export default class FromDemo extends React.Component {
   handleSubmit = (e)=>{
    e.preventDefault();
    console.log(this.props.getFieldValue())
   }
    render() {
        return(
            
{/*
handleSubmit
*/}
) } }

接下来就是如何实现:
先创建一个creat.js:

import React from 'react';

export const formCreate = WrappedComponent => class extends React.Component {
    state = { 
        fields: {} 
    };

    onChange = key => e =>{
        this.setFieldValue(key, e.target.value)
	}
    
    setFieldValue = (fieldName, value) => this.setState(state => {
        state.fields[fieldName] = value;
        return state;
    })

    getFieldValue = () => this.state.fields;
    
    getField = fieldName =>{
		return {
            onChange:this.onChange(fieldName),
            value: this.state.fields[fieldName] ||''
		}
	}
    
    setInitialValue = (fieldName, value) => this.setFieldValue(fieldName, value);
    
    render() {
        const props = {
            ...this.props,
            getField: this.getField,
            getFieldValue: this.getFieldValue,
            setFieldValue: this.setFieldValue,
            setInitialValue: this.setInitialValue,
        };
        return  this.instanceComponent = ref} />;
    }
};

这个formCreate是一个高阶组件,这样可以传递props在外部调用 this.props.getFieldValue() 来获取输入框中的值,这里面的核心方法就是onChange来获取改变的值,并通过setFieldValue这个方法赋值给 this.state.fields,通过state.fields[fieldName] = value;这种方式统一简化处理不同的key。

fileitem.js的实现:

import React from 'react';
 
export default class Item extends React.Component {
    form = this.props.children._owner.stateNode.props;
    
    componentDidMount() {
        this.updateInitialValue();
    }
    
    componentDidUpdate() {
        this.updateInitialValue();
    }
    
    updateInitialValue() {
        let { fieldName, initialValue } = this.props;
        (this.initialValue !== initialValue) &&
        (this.initialValue = initialValue) &&
        this.form.setInitialValue(fieldName, initialValue);
    }
    
    render() {
        let { title, fieldName } = this.props;
        return(
            
{title}
{/* 通过 React.cloneElement 向子组件传递 state 及 function */} {React.cloneElement(this.props.children, { ...this.form.getField(fieldName) })}
) } }

通过 React.cloneElement 向子组件传递 state 及 function,外部使用的时候 不需要做什么处理。通过 form = this.props.children._owner.stateNode.props;获取到高阶组件使用其中的方法,this.form.setInitialValue(fieldName, initialValue);填充输入框的默认值。{ ...this.form.getField(fieldName) }会获取到高阶组件中的getField方法中返回的onChangevalue绑定到克隆的输入框组件。
最后统一暴露接口,From.js:

import React from 'react';
import Item from './fileitem';
import { formCreate } from './creat';

class Form extends React.Component {
    static formCreate = formCreate
    static Item = Item
    render() {
        return(
            
{this.props.children}
) } } export default Form;

一个非常简单表单组件就完成了,只有获取值的操作,没有数据验证的功能。
antd官方地址:点我查看Form组件官方实现

你可能感兴趣的:(实现一个React From组件)