表单的字段一般包括两部分,一部分是标题,另一部分是内容。ZentForm通过getControlGroup这一高阶函数对结构和样式做了一些封装,它的入参是要显示的组件:
export default Control => {
render() {
return (
<div className={groupClassName}>
<label className="zent-form__control-label">
{required ? <em className="zent-form__required">*</em> : null}
{label}
</label>
<div className="zent-form__controls">
<Control {...props} {...controlRef} />
{showError && (
<p className="zent-form__error-desc">{props.error}</p>
)}
{notice && <p className="zent-form__notice-desc">{notice}</p>}
{helpDesc && <p className="zent-form__help-desc">{helpDesc}</p>}
</div>
</div>
);
}
}
这里用到的label和error等信息,是通过Field组件传入的:
<Field
label="预约门店:"
name="dept"
component={CustomizedComp}
validations={{
required: true,
}}
validationErrors={{
required: '预约门店不能为空',
}}
required
/>
这里的CustomizedComp是通过getControlGroup封装后返回的组件。
字段与表单之间的交互是一个需要考虑的问题,表单需要知道它包含的字段值,需要在适当的时机对字段进行校验。ZentForm的实现方式是在Form的高阶组件内维护一个字段数组,数组内容是Field的实例。后续通过操作这些实例的方法来达到取值和校验的目的。
ZentForm的使用方式如下:
class FieldForm extends React.Component {
render() {
return (
<Form>
<Field
name="name"
component={CustomizedComp}
</Form>
)
}
}
export default createForm()(FieldForm);
其中Form和Field是组件库提供的组件,CustomizedComp是自定义的组件,createForm是组件库提供的高阶函数。在createForm返回的组件中,维护了一个fields的数组,同时提供了attachToForm和detachFromForm两个方法,来操作这个数组。这两个方法保存在context对象当中,Field就能在加载和卸载的时候调用了。简化后的代码如下:
/**
* createForm高阶函数
*/
const createForm = (config = {}) => {
...
return WrappedForm => {
return class Form extends Component {
constructor(props) {
super(props);
this.fields = [];
}
getChildContext() {
return {
zentForm: {
attachToForm: this.attachToForm,
detachFromForm: this.detachFromForm,
}
}
}
attachToForm = field => {
if (this.fields.indexOf(field) < 0) {
this.fields.push(field);
}
};
detachFromForm = field => {
const fieldPos = this.fields.indexOf(field);
if (fieldPos >= 0) {
this.fields.splice(fieldPos, 1);
}
};
render() {
return createElement(WrappedForm, {...});
}
}
}
}
/**
* Field组件
*/
class Field extends Component {
componentWillMount() {
this.context.zentForm.attachToForm(this);
}
componentWillUnmount() {
this.context.zentForm.detachFromForm(this);
}
render() {
const { component } = this.props;
return createElement(component, {...});
}
}
内容版权声明:除非注明,否则皆为本站原创文章。
