实现一个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(
            <div>
              <Form onSubmit={this.handleSubmit}>
                <Form.Item fieldName='username' initialValue='1'>
                    <input/>
                </Form.Item>
                <Form.Item fieldName='password' initialValue='2'>
                    <input/>
                </Form.Item>
                {/* <div onClick={this.handleSubmit}>handleSubmit</div> */}
                <input type="submit" value="提交" />
              </Form>
            </div>
        )
    }
}

接下来就是如何实现:
先创建一个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 <WrappedComponent {...props} ref={ref => 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(
            <div>
                <div>{title}</div>
                {/* 通过 React.cloneElement 向子组件传递 state 及 function */}
                {React.cloneElement(this.props.children, { ...this.form.getField(fieldName) })}
            </div>
        )
    }
}

通过 React.cloneElement 向子组件传递 state 及 function,外部使用的时候 <input/> 不需要做什么处理。通过 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(
            <form>
                {this.props.children}
            </form>
        )
    }
}
export default Form;

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值