antd原始碼解讀(9)- Form

markzzw發表於2017-12-04

Form 表單

這個元件貌似比較獨特,在官網上面的每一個例子都是使用了Form.create()這個HOC的方法去進行的建立相應的Form元件所以對於表單元件我們主要講的應該就會是create這個高階函式

Form.create

這是一個高階函式,傳入的是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建立的是一個什麼

createDOMFormrc-form庫中引用的,從程式碼一層層的查詢下去發現建立一個form元件的主要程式碼是在createBaseForm.js這個檔案中

function createBaseForm(option = {
}, mixins = []
)
{
const {
...
} = option;
return function decorate(WrappedComponent) {
const Form = createReactClass({
...
});
return argumentContainer(Form, WrappedComponent);

};

}複製程式碼

這又是一個高階函式,在這個函式中先建立了一個Form元件,然後使用argumentContainer函式進行包裝在傳出,傳出的是一個新的元件

這個新的元件將會擁有傳入元件以及高階元件中的所有屬性

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,這個庫是用於解決高階元件不能夠使用傳入的元件的靜態方法這個問題的

具體在react官網上面也有相應的解釋,使用了這個方法就能夠將傳入元件的靜態方法也完全拷貝到高階函式返回的元件中。

從現在看來之前程式碼中的formWrapper就是一個接受傳入元件,然後再將元件進行轉化成為一個新增了antd自己的Form高階元件。

總結

通過這個元件的這個函式,加深了我對HOC的使用和認識,也對裝飾器有了更深認識,技能點+1。

來源:https://juejin.im/post/5a23f734f265da431280bcbe

相關文章