react + antd 封装通过json数组形式的Form表单
1. 假设你已经安装好了依赖,已经可以通过react + antd搭建页面了2.搭建Form组件模子3. 老生长谈的,配合Row与Col组件4. fields json数组的格式制定5. 尝试一下效果预览 6. 那么,怎么在父组件上获取组件上表单项的值呢?6.1 通过ref效果预览 6.2 使用 rc-form 提供的 wrappedComponentRef效果预览 6.3 通过回调结合组件的componentDidMount生命钩子效果预览最近在搞react + antd,在弄form表单的时候,觉得没写一次都要重新写一次Form, Form.Item,感觉有些麻烦;就想啊,能不能像vue+element那样通过json配置的方式,实现一个form组件
1. 假设你已经安装好了依赖,已经可以通过react + antd搭建页面了
以下是我的项目主要依赖,版本不同,写法可能也有些不同:
"react": "^18.1.0","react-dom": "^18.1.0","antd": "^3.26.19","react-router": "^3.2.0",
2.搭建Form组件模子
import React from "react"import {Form, Col, Row} from "antd"class Index extends ponent {render() {return (<Form></Form>)}}export default Form.create()(Index)
3. 老生长谈的,配合Row与Col组件
主要是用 Col来做Form.Item的容器
const Item = Form.Itemclass Index extends ponent {//这个地方就是我们用来遍历父组件传过来的json数组配置,我们就定义这个配置属性是fieldsgetFormField = () => {//这里要注意以下 form是通过Form.create()(xxx)const {form, getFieldDecorator, fields} = this.propsreturn fields.map((item, index)=>(<Col key={item.field + item.label + index} ><Item label={item.label}>{getFieldDecorator(item.field, {//...表单项配置})(//表单项配置)}</Item></Col>))}render() {return (<Form><Row gutter={24}>{this.getFormField()}</Row></Form>)}}//...省略
4. fields json数组的格式制定
// {label: "姓名", field: "name", attrs: {rules: [{ required: true, message: "请输入!" }], initialValue: "张三",} component: <Input allowClear placeholder="请输入姓名" />}// 那么 getFormField 方法也就可以完善了getFormField = () => {//这里要注意以下 form是通过Form.create()(xxx)const {form, span = 6, fields} = this.propsconst {getFieldDecorator} = formreturn fields.map((item, index)=>(<Col span={span} key={item.field + item.label + index} ><Item label={item.label}>{getFieldDecorator(item.field, {...item.attrs})(ponent)}</Item></Col>))}
5. 尝试一下
父组件
//导入Form组件import FormPage from "./components/form"import {Input, InputNumber} from 'antd'function App() {const fields = [{label: "姓名", field: "name", attrs: {rules: [{required: true, message: "请输入!" }] }, component: <Input allowClear placeholder="请输入姓名" /> },{label: "年龄", field: "age", attrs: {rules: [{required: true, message: "请输入!" }] }, component: <InputNumber allowClear placeholder="请输入年龄" style={{width: "100%"}}/> },]return (<div className="App"><FormPage fields={fields}/></div>);}
效果预览
6. 那么,怎么在父组件上获取组件上表单项的值呢?
6.1 通过ref
// 父组件中创建一个ref,绑定组件import React from "react"import FormPage from "./components/form"function App() {//创建ref对象const fromRef = React.createRef()const handleForm = ()=> {//使用ref对象formRef.current.validateFields((err, vals) => {if(err) returnconsole.log(vals)})}//...省略return (<div className="App">// ref对象与非状态组件绑定<FormPage fields={fields} ref={fromRef}/><div style={{textAlign: "right"}}><Button type="primary" onClick={handleForm}>获取</Button></div></div>);}
效果预览
6.2 使用 rc-form 提供的 wrappedComponentRef
import React, {useState} from "react"import FormPage from "./components/form"function App() {const EnhancedForm = FormPage//非状态组件,用hooks定义变量const [form, setform] = useState();const handleForm = ()=> {//使用form.props.form.validateFields((err, vals) => {if(err) returnconsole.log(vals)})}//...省略return (<div className="App"><EnhancedForm wrappedComponentRef={(form) => setform(form)} fields={fields} /><div style={{textAlign: "right"}}><Button type="primary" onClick={handleForm}>获取</Button></div></div>);}
效果预览
6.3 通过回调结合组件的componentDidMount生命钩子
这种方法需要我们稍稍改造一下FormPage组件
//...省略class Index extends ponent {//...省略getForm = ()=> {const {form} = this.propsthis.props.getForm && this.props.getForm(form)}componentDidMount() {this.getForm()}//...省略}//...省略
父组件使用
import React, {useState} from "react"import FormPage from "./components/form"function App() {const [form, setform] = useState();const handleForm = ()=> {console.log(form)//使用form.validateFields((err, vals) => {if(err) returnconsole.log(vals)})}//...省略return (<div className="App"><FormPage fields={fields} getForm={(f) => setform(f)}/><div style={{textAlign: "right"}}><Button type="primary" onClick={handleForm}>获取</Button></div></div>);}