原创:antd源码解读- Form

Posted 创宇前端

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原创:antd源码解读- Form相关的知识,希望对你有一定的参考价值。

文/张泽玮

Form 表单

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

Form.create

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

 
   
   
 
  1.  static create = function<TOwnProps>(options: FormCreateOption<TOwnProps> = {}): ComponentDecorator<TOwnProps> {

  2.    const formWrapper = createDOMForm({

  3.      fieldNameProp: 'id',

  4.      ...options,

  5.      fieldMetaProp: FIELD_META_PROP,

  6.    });

  7.    /* eslint-disable react/prefer-es6-class */

  8.    return (Component) => formWrapper(createReactClass({

  9.      propTypes: {

  10.        form: PropTypes.object.isRequired,

  11.      },

  12.      childContextTypes: {

  13.        form: PropTypes.object.isRequired,

  14.      },

  15.      getChildContext() {

  16.        return {

  17.          form: this.props.form,

  18.        };

  19.      },

  20.      componentWillMount() {

  21.        this.__getFieldProps = this.props.form.getFieldProps;

  22.      },

  23.      deprecatedGetFieldProps(name, option) {

  24.        warning(

  25.          false,

  26.          '`getFieldProps` is not recommended, please use `getFieldDecorator` instead, '

  27.          'see: https://u.ant.design/get-field-decorator',

  28.        );

  29.        return this.__getFieldProps(name, option);

  30.      },

  31.      render() {

  32.        this.props.form.getFieldProps = this.deprecatedGetFieldProps;

  33.        const withRef: any = {};

  34.        if (options.withRef) {

  35.          withRef.ref = 'formWrappedComponent';

  36.        } else if (this.props.wrappedComponentRef) {

  37.          withRef.ref = this.props.wrappedComponentRef;

  38.        }

  39.        return <Component {...this.props} {...withRef} />;

  40.      },

  41.    }));

  42.  };

从代码看出这个函数返回的是一个函数,接受一个组件作为参数,但是返回什么不是很清楚,所以需要再看看 createDOMForm创建的是一个什么。

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

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

  2.  const { ... } = option;

  3.  return function decorate(WrappedComponent) {

  4.    const Form = createReactClass({ ... });

  5.    return argumentContainer(Form, WrappedComponent);

  6.  };

  7. }

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

这个新的组件将会拥有传入组件以及高阶组件中的所有属性

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

  2. export function argumentContainer(Container, WrappedComponent) {

  3.  /* eslint no-param-reassign:0 */

  4.  Container.displayName = `Form(${getDisplayName(WrappedComponent)})`;

  5.  Container.WrappedComponent = WrappedComponent;

  6.  return hoistStatics(Container, WrappedComponent);

  7. }

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

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

从现在看来之前代码中的 formWrapper就是一个接受传入组件,然后再将组件进行转化成为一个添加了antd自己的Form高阶组件。

总结

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


以上是关于原创:antd源码解读- Form的主要内容,如果未能解决你的问题,请参考以下文章

Antd form表单中input失效,无法输入字符串,只能输入单个字符

OpenFeign 和 Hystrix 的源码解读(原创)

Vue使用antd组件a-form-model-实现数据连续添加

Vue使用antd组件a-form-model-实现数据连续添加

Vue使用antd组件a-form-model-实现数据连续添加

ant-design-vue之form源码解读