前言

通过模拟 rc-form 的实现思路,能够学习一下 hoc 的应用场景。

裸露 createForm() 函数

通过 createForm 函数,返回一个组件。该组件拓展了咱们的一些办法。

export function createForm(Cmp) {  return class extends Component {    getFieldDecorator = () => {}        getFieldsValue = () => {}        getFieldValue = () => {}        setFieldValue = () => {}        validateFields = () => {}      form = () => {      return {        getFieldDecorator: this.getFieldDecorator,        getFieldValue: this.getFieldValue,        getFieldsValue: this.getFieldsValue,        setFieldValue: this.setFieldValue,        validateFields: this.validateFields,      }    }        render() {      const form = getForm()      return <Cmp {...this.props} form={form} />    }  }}

实现 getFieldDecorator

应用办法

<div>  {getFieldDecorator('username', {rules: { require: true, message: '请输出用户名' })(<input placeholder="请输出用户名" />)}</div>

能够看出,该函数接管两个参数,第一个是字段名,第二个是它的规定。又接着返回了一个接管一个组件的函数,最终返回一个加工后的组件。当初咱们开始简略实现一下。

constructor(){  // ...  this.state = {}  this.options = {}}
getFieldDecorator = (fieldName, option) => InputCmp => {  // 保留数据和选项  if (this.state[fieldName] === undefined) this.setState({ [fieldName]: '' })  this.options[fieldName] = option  // 返回一个解决后的组件  return React.cloneElement(InputCmp, {    name: fieldName,    value: this.state[fieldName],    onChange: this.handleChange,  })}

定义 handleChange 事件

handleChange = (e) => {  const { name, value } = e.target  this.setState({ [name]: value })}

实现 getFieldValue

间接把 state 的数据返回即可

getFieldsValue = () => {  return {...this.state}}

实现 getFieldsValue

通过传进来的名字,返回对应的数据

getFieldValue = name => {  return this.state[name]}

实现 setFieldValue

间接将传进来的数据合并起来即可

setFieldValue = state => {  this.setState(state)}

实现 validateFields

该办法接管一个回调函数,通过遍历options的规定,在判断相应的值,返回谬误数据以及state的数据

validateFields = callback => {  const err = []  for (let fieldName in this.options) {    const rules = this.options[fieldName]?.rules    const value = this.state[fieldName]    if(rules && rules.require && rules.message && !value) {      err.push({        [fieldName]: rules.message      })    }  }  // 判断 err 是否有数据  if (err.length === 0) {    callback(null, { ...this.state })  } else {    callback(err, { ...this.state })  }}

最终代码

import React, { Component } from 'react'export function createForm(Cmp) {  return class extends Component {    constructor(props) {      super(props)      this.state = {}      this.options = {}    }    handleChange = e => {      const { name, value } = e.target      this.setState({ [name]: value })    }    validateFields = callback => {      const err = []      for (let fieldName in this.options) {        const rules = this.options[fieldName]?.rules        if (rules && rules.require && rules.message && !this.state[fieldName]) {          err.push({            [fieldName]: rules.message,          })        }      }      if (err.length === 0) {        callback(null, { ...this.state })      } else {        callback(err, { ...this.state })      }    }    getFieldDecorator = (fieldName, option) => InputCmp => {      this.options[fieldName] = option      if (this.state[fieldName] === undefined) this.setState({ [fieldName]: '' })      return React.cloneElement(InputCmp, {        name: fieldName,        value: this.state[fieldName],        onChange: this.handleChange,      })    }    getFieldValue = name => {      return this.state[name]    }    getFieldsValue = () => {      return { ...this.state }    }    setFieldValue = state => {      this.setState(state)    }    getForm = () => {      return {        getFieldDecorator: this.getFieldDecorator,        getFieldValue: this.getFieldValue,        getFieldsValue: this.getFieldsValue,        setFieldValue: this.setFieldValue,        validateFields: this.validateFields,      }    }    render() {      const form = this.getForm()      return <Cmp {...this.props} form={form} />    }  }}