antd源码解读(9)- Form

Form 表单

这个组件貌似比较独特,在官网上面的每个例子都是使用了Form.create()这个HOC的方法去进行的建立相应的Form组件 因此对于表单组件咱们主要讲的应该就会是create这个高阶函数html

Form.create

这是一个高阶函数,传入的是react组件,返回一个新的react组件,在函数内部会对传入组件进行改造,添加上必定的方法用于进行一些秘密操做 若是有对高阶组件有想要深刻的请移步这里,咱们这里不作过多的深究。接下来咱们直接看这个函数的代码react

static create = function<TOwnProps>(options: FormCreateOption<TOwnProps> = {}): ComponentDecorator<TOwnProps> {
    const formWrapper = createDOMForm({
      fieldNameProp: 'id',
      ...options,
      fieldMetaProp: FIELD_META_PROP,
    });

    /* eslint-disable react/prefer-es6-class */
    return (Component) => formWrapper(createReactClass({
      propTypes: {
        form: PropTypes.object.isRequired,
      },
      childContextTypes: {
        form: PropTypes.object.isRequired,
      },
      getChildContext() {
        return {
          form: this.props.form,
        };
      },
      componentWillMount() {
        this.__getFieldProps = this.props.form.getFieldProps;
      },
      deprecatedGetFieldProps(name, option) {
        warning(
          false,
          '`getFieldProps` is not recommended, please use `getFieldDecorator` instead, ' +
          'see: https://u.ant.design/get-field-decorator',
        );
        return this.__getFieldProps(name, option);
      },
      render() {
        this.props.form.getFieldProps = this.deprecatedGetFieldProps;

        const withRef: any = {};
        if (options.withRef) {
          withRef.ref = 'formWrappedComponent';
        } else if (this.props.wrappedComponentRef) {
          withRef.ref = this.props.wrappedComponentRef;
        }
        return <Component {...this.props} {...withRef} />; }, })); }; 复制代码

从代码看出这个函数返回的是一个函数,接受一个组件做为参数,可是返回什么不是很清楚,因此须要再看看createDOMForm建立的是一个什么es6

createDOMFormrc-form库中引用的,从代码一层层的查找下去发现建立一个form组件的主要代码是在createBaseForm.js这个文件中antd

function createBaseForm(option = {}, mixins = []) {
  const { ... } = option;

  return function decorate(WrappedComponent) {
    const Form = createReactClass({ ... });

    return argumentContainer(Form, WrappedComponent);
  };
}
复制代码

这又是一个高阶函数,在这个函数中先建立了一个Form组件,而后使用argumentContainer函数进行包装在传出,传出的是一个新的组件app

这个新的组件将会拥有传入组件以及高阶组件中的全部属性函数

import hoistStatics from 'hoist-non-react-statics';

export function argumentContainer(Container, WrappedComponent) {
  /* eslint no-param-reassign:0 */
  Container.displayName = `Form(${getDisplayName(WrappedComponent)})`;
  Container.WrappedComponent = WrappedComponent;
  return hoistStatics(Container, WrappedComponent);
}
复制代码

argumentContainer函数使用了一个库hoist-non-react-statics,这个库是用于解决高阶组件不可以使用传入的组件的静态方法这个问题的ui

具体在react官网上面也有相应的解释,使用了这个方法就可以将传入组件的静态方法也彻底拷贝到高阶函数返回的组件中。this

从如今看来以前代码中的formWrapper就是一个接受传入组件,而后再将组件进行转化成为一个添加了antd本身的Form高阶组件。spa

总结

经过这个组件的这个函数,加深了我对HOC的使用和认识,也对装饰器有了更深认识,技能点+1。eslint

相关文章
相关标签/搜索