在antd3
中使用高阶组件的方式实现Form
表单,我们简单说一下高阶组件的实现思路,我们使用一个createForm
高阶组件,它返回一个类组件,像上面一样我们需要一个地方存储所有的表单值以及创建修改值的方法,我们在createForm
里面用this.state
存储表单值,并使用getFieldDecorator
方法为input
组件添加onChange
事件,以及value
,value
从state
中获取,这样通过setState方法改变值时视图也会更新,当input
值改变时通过setState
将改变更新到state
上面。setFieldsValue、getFieldsValue
这些方法很简单就不说了。
代码如下
import React, {Component} from "react";
export default 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});
getFieldDecorator = (field, option) => InputCmp => {
this.options[field] = option;
return React.cloneElement(InputCmp, {
name: field,
value: this.state[field] || "",
onChange: this.handleChange
});
setFieldsValue = newStore => {
this.setState(newStore);
getFieldsValue = () => {
return this.state;
validateFields = callback => {
let err = [];
for (let field in this.options) {
if (this.state[field] === undefined) {
err.push({
[field]: "err"
});
if (err.length === 0) {
callback(null, this.state);
} else {
callback(err, this.state);
getForm = () => {
return {
form: {
getFieldDecorator: this.getFieldDecorator,
setFieldsValue: this.setFieldsValue,
getFieldsValue: this.getFieldsValue,
validateFields: this.validateFields
render() {
return <Cmp {...this.props} {...this.getForm()} />;
import React, {Component} from "react";
import createForm from "../components/my-rc-form/";
import Input from "../components/Input";
const nameRules = {required: true, message: "请输入姓名!"};
const passworRules = {required: true, message: "请输入密码!"};
@createForm
class MyRCForm extends Component {
constructor(props) {
super(props);
componentDidMount() {
this.props.form.setFieldsValue({username: "default"});
submit = () => {
const {getFieldsValue, validateFields} = this.props.form;
validateFields((err, val) => {
if (err) {
console.log("err", err);
} else {
console.log("校验成功", val);
});
render() {
console.log("props", this.props);
const {getFieldDecorator} = this.props.form;
return (
<h3>MyRCForm</h3>
{getFieldDecorator("username", {rules: [nameRules]})(
<Input placeholder="Username" />
{getFieldDecorator("password", {rules: [passworRules]})(
<Input placeholder="Password" />
<button onClick={this.submit}>submit</button>
</div>
export default MyRCForm;
实现antd中Form、Form.Item组件初始化项目使用create-react-app初始化项目后创建MyRcFieldForm文件,代码如下import React, { Component, useEffect } from 'react'; import Form, { Field } from 'rc-field-form';//import Form, { Field } from './components/my-rc-field-form/';import Input fro
一个非常简单的HOC,用于AntD Form.Item,使其仅显示文本而不显示组件。 当您需要表单的查看模式时,此功能很有用。
yarn add form-item-view-hoc
这是将此HOC与AntD Form.Item一起使用的示例
import React from "react" ;
import ReactDOM from "react-dom" ;
import withFormItemView from "form-item-view-hoc" ;
import { Form , Input , Switch } from "antd" ;
const CustomFormItem = withFormItemView ( Form . Item ) ;
function MyForm ( props ) {
const
记住:setFieldsValue的字段要对应得上
解决antd的Form组件setFieldsValue的警告
使用antd的Form组件setFieldsValue可能会出现You cannot set a form field before rendering a field associated with the value.警告,字面意义去看是说在 render之前设置了表单值的问题。
在使用setFieldsValue给表单Form的某一个filed赋值时,可能掺杂了非表单控件中的字段,Form表单在赋值和渲染时发现有些字段无法渲染在现有的字段(因为不存在),所以就会报出这
Antd 中的组件大部分基于蚂蚁金服的组件库 react-component。antd 与 react-component 都是开源项目,阅读其源码可以给我们带来很多收益,比如:
了解各式各样的组件背后的实现思想
怎样去实现一个对开发和用户都友好的组件,即简单易用,便于扩展。
学习一些我们在写业务代码时不太会用到的 React 高级用法
但是阅读过 Antd 源码就会发现,代码量巨大而且...
要获取 `Form.Item` 下的 `Select` 组件中的所有选项,可以通过 `React` 的 `ref` 属性来实现。具体步骤如下:
1. 在 `Form.Item` 中使用 `ref` 属性创建一个 `ref` 对象,如:
<Form.Item label="Label" name="name" ref={selectRef}>
<Select>
<Option value="value1">Option 1</Option>
<Option value="value2">Option 2</Option>
<Option value="value3">Option 3</Option>
</Select>
</Form.Item>
这里的 `selectRef` 是在 `useState` 中创建的,如:
const [selectRef, setSelectRef] = useState(null);
2. 在 `useEffect` 中等待 `Form.Item` 和 `Select` 组件渲染完成后,通过 `selectRef.current.props.children` 来获取 `Select` 组件下的所有 `Option` 组件,如:
useEffect(() => {
if (selectRef && selectRef.current) {
const options = Array.from(selectRef.current.props.children).map(option => {
return {
value: option.props.value,
label: option.props.children
console.log(options);
}, [selectRef]);
这里使用 `Array.from` 将 `Select` 的子组件转换为数组,然后遍历数组中的每个 `Option` 组件,将其值和标签存储在一个对象中,最后将所有对象存储在一个数组中并输出到控制台中。
注意:在 `useEffect` 中需要将 `selectRef` 作为依赖项传入,以确保 `Form.Item` 和 `Select` 组件渲染完成后再执行代码。