简单模拟 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
方法中返回的onChange
和value
绑定到克隆的输入框组件。
最后统一暴露接口,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组件官方实现