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

相關文章
相關標籤/搜索