hoc实现表单组件的设计思路
前言
通过模仿 rc-form 的实现思路,可以学习一下 hoc 的使用场景。
暴露 createForm() 函数
通过 createForm 函数,返回一个组件。该组件拓展了我们的一些方法。
export function createForm(Cmp) {
return class extends Component {
getFieldDecorator = () => {}getFieldsValue = https://www.it610.com/article/() => {}getFieldValue = https://www.it610.com/article/() => {}setFieldValue = https://www.it610.com/article/() => {}validateFields = () => {}form = () => {
return {
getFieldDecorator: this.getFieldDecorator,
getFieldValue: this.getFieldValue,
getFieldsValue: this.getFieldsValue,
setFieldValue: this.setFieldValue,
validateFields: this.validateFields,
}
}render() {
const form = getForm()
return
}
}
}
实现 getFieldDecorator 使用方法
{getFieldDecorator('username', {rules: { require: true, message: '请输入用户名' })()}
可以看出,该函数接收两个参数,第一个是字段名,第二个是它的规则。又接着返回了一个接收一个组件的函数,最终返回一个加工后的组件。现在我们开始简单实现一下。
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 = https://www.it610.com/article/() => {
return {...this.state}
}
实现 getFieldsValue 【hoc实现表单组件的设计思路】通过传进来的名字,返回对应的数据
getFieldValue = https://www.it610.com/article/name => {
return this.state[name]
}
实现 setFieldValue 直接将传进来的数据合并起来即可
setFieldValue = https://www.it610.com/article/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 = https://www.it610.com/article/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 = https://www.it610.com/article/name => {
return this.state[name]
}getFieldsValue = https://www.it610.com/article/() => {
return { ...this.state }
}setFieldValue = https://www.it610.com/article/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
}
}
}
推荐阅读
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- MybatisPlus使用queryWrapper如何实现复杂查询
- python学习之|python学习之 实现QQ自动发送消息
- 孩子不是实现父母欲望的工具——林哈夫
- opencv|opencv C++模板匹配的简单实现
- Node.js中readline模块实现终端输入
- java中如何实现重建二叉树
- 人脸识别|【人脸识别系列】| 实现自动化妆
- paddle|动手从头实现LSTM
- pytorch|使用pytorch从头实现多层LSTM