antd vue form 手动校验_Antd of React 源码阅读系列——Form

089ac84b84949f0ce249550591b2028b.png

最近开发中使用到了Antd这款世界上最受欢迎的(前段时间还是第二)React-UI框架,而这个表单(Form)我看眉清目秀的,来,让哥哥来康康······

功能

  1. 收集输入表单容器(input、select)内容
  2. 根据校验规则进行内容校验 并 显示结果

API

  1. create
  2. getFieldDecorator
  3. getFieldValue
  4. getFieldsValue
  5. setFieldsValue
  6. ······(to do)

路径/components/form/Form.tsx

import createDOMForm from 'rc-form/lib/createDOMForm';
...
static create = function create<TOwnProps extends FormComponentProps>(
    options: FormCreateOption<TOwnProps> = {},
  ): FormWrappedProps<TOwnProps> {
    return createDOMForm({
      fieldNameProp: 'id',
      ...options,
      fieldMetaProp: FIELD_META_PROP,
      fieldDataProp: FIELD_DATA_PROP,
    });
  };

我们可以看到,Antd 的Form 其实是调用了一个叫做 createDOMForm的方法,而createDOMForm实来自于rc-form(同为蚂蚁开发的一个react HOC form 组件),于是我知道,Antd-Form 实际是对 rc-form 进行的UI封装;

所以这里直接从 rc-formcreateDOMForm方法来康起即可。

rc-form

React High Order Form Component

路径:/src/createDOMForm.js

无论是 Antd的 create 还是rc-form 本身的createForm 全都基于createBaseForm的实现;

路径:/src/createBaseForm.js

645 行代码着实吓我一跳,但是仔细观之,其实通过简化还是可以发现:

function createBaseForm(option = {}, mixins = []) {
  return function decorate(WrappedComponent) {
    const Form = createReactClass({
       render() {
        return <WrappedComponent {...props} />
      }
    });
    return Form;
  }
}

这其实是一个高阶组件(HOC)的形式

那么问题来了:什么是高阶组件(HOC)呢?(我很少实际代码中写HOC)

说白了,就是一个函数,这个函数的样子是

function HOC (WrappedComponent) {
  return class xxx extends React.Component {
    constructor(props) {
      ...
    }
    render() {
      return (
        <WrappedComponent
          ref={this.props.wrappedComponentRef}
        />
      )
    }
  }
}

传入:组件

输入:组件

在组件上挂载一些props或者实现一些业务逻辑从而返回一个新的组件,UI由元组件提供;

那么接续上文 createBaseForm 其实就是将元组件(Form 容器)包裹实现各种新逻辑(如 上问题到的各种API方法)从而返回新的Form组件;

接下来具体问题具体看,使用Form组件的时候一般长用到几个方法:

  1. getFieldDecorator
  2. getFieldValue
  3. getFieldsValue
  4. setFieldsValue
  5. 等等(to do)

getFieldDecorator

因为之前有用Fusion(react-ui组件框架),他的表单绑定写法是:

const init = this.field.init;
return (
  <div>
    <Input {...init('name',{initValue:'first value'})} />
    <button onClick={this.onClick}>获取数据</button>
  </div>
)

同样,rc-form 也提供了一种类似于这种绑定表单元素的方法,用这种方法给每个表单元素上绑定【名称】【校验规则】【初始值】······各种options

// getFieldProps
<form>
  <input {...getFieldProps('name', { ...options })} />
</form>

// option
option.valuePropName
option.getValueProps
option.initialValue
option.rules
...

而 getFieldDecorator 方法呢,似乎更加优雅,他就类似于之前的createBaseForm是一个HOC:

把 option.valuePropName,option.getValueProps,option.initialValue,option.rules等各种props挂在 被包含的表单组件上;

{getFieldDecorator('username', {
  rules: [{ required: true, message: 'Please input your username!' }],
})(
  <input
    prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />}
    placeholder="Username"
    />,
)}

源码同样简化一下:

getFieldDecorator(name, fieldOption) {
  const props = this.getFieldProps(name, fieldOption);
  // 用HOC的方式把props挂在被包含组件上
  return (fieldElem) => {
    return React.cloneElement(fieldElem, {
      ...props,
      ...this.fieldsStore.getFieldValuePropValue(fieldMeta),
    });
  };
}

// 这里出现了一个 fieldsStore,this.fieldsStore = createFieldsStore(fields || {});
// 在创建组件的过程中,将各个属性方法挂载在被包含组件上,而某些具体的方法实现则是在 createFieldsStore 中完成的;

那么问题来,createFieldsStore 是干嘛的?(存储、读取、设置表单数据)

打开瞧瞧:

路径:/src/createFieldsStore.js

原来,像getFieldsValue,getFieldValue,setFieldsInitialValue等用到的对于表单数据的 获取,存储等操作全是在这个文件中包裹的;

getFieldValue

功能: 功能是从存储的数据中,查找出指定表单名的数据

调用链:getFieldValue(name) -> getNestedField(name) [// 根据传入的name,调用getter函数(getValueFromFields)获取值] -> getValueFromFields (fullName, fields)

// 
getValueFromFields(name, fields) {
  const field = fields[name];
  if (field && 'value' in field) {
    return field.value;
  }
  const fieldMeta = this.getFieldMeta(name);
  return fieldMeta && fieldMeta.initialValue;
}

// fields 从 createBaseForm 中来
const {
  validateMessages,
  onFieldsChange,
  onValuesChange,
  mapProps = identity,
  mapPropsToFields, // ***
  fieldNameProp,
  fieldMetaProp,
  fieldDataProp,
  formPropName = 'form',
  name: formName,
  withRef,
} = option;

const fields = mapPropsToFields && mapPropsToFields(this.props);

// 通过使用 onFieldsChange 与 mapPropsToFields,可以把表单的数据存储到上层组件或者 Redux、dva 中

setFieldsValue

// 明天接着更新

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值