antd rapid development (Form article)

antd rapid development (Form article)

Foreword

As has been doing business in Taiwan, particularly the project background, but the background characteristics of the project are: a large number of lists and a large number of forms, will reduce the duplication of development efficiency, so here I summed up what use antdcomponents to build formquick method. I hope to be useful.

Traditional Form build

First, build a form of traditional form, the code might look like this child

import React from 'react';
import { Form, Input } from 'antd';

@Form.create()
class MyTestForm extends React.Component {
  render() {
    const { form: { getFieldDecorator } } = this.props;
    return(
      <Form>
        <Form.Item label='姓名'>
          {
            getFieldDecorator('username', {
              rules: [
                {
                  required: true,
                  message: '这是必填项'
                }
              ]
            })(<Input placeholder="placeholder" />)
          }
        </Form.Item>
        <Form.Item label='密码'>
          {
            getFieldDecorator('password', {
              rules: [
                {
                  required: true,
                  message: '这是必填项'
                }
              ]
            })(<Input placeholder="placeholder" />)
          }
        </Form.Item>
      </Form>
    )
  }
}

export default MyTestForm;

At present, only two individual tables, the code looks pretty clear, if this form is very complex forms, there are more form item, this code will be very long, it is not convenient maintenance and development, the most important again a big form, you'll still need to write so much code. This will affect the open efficiency.

Form optimized

What we want is, try to write less (not write) repetitive code so that a higher reusability of code. I did some this optimization, the main flow is shown:

Several major points:

  • The lowest level, the most important part pulled out, that is, BaseItemthe components, BaseItemthe ability to have is the ability to form, the ability of the two-way binding, pure components, does not contain any UI aspects of things.
  • Something the UI layer also pulled out separately, in order to facilitate future expansion of UI level. (For example, wanted to design their own set of UI style, only used directly to develop a new UI aspects of things, but the code instead of atomic layer assembly of the heart).
  • Each form of information pulled into the configuration file so that the page maintenance more convenient.

Possible code

//BaseItem.js(原子层)
const BaseItem = (props) => {
  const { form: { getFieldDecorator }, config } = props;
  const { name, children, ...argv } = config;
  return name ? getFieldDecorator(name, { ...argv })(children) : (children);
}

export default BaseItem;
//ItemLayout.js(UI组件)
import React from 'react';
import { Form } from 'antd';

//Layout也可以用自己的UI组件
const Layout = ({ config: { itemOptions }, children }) =>
  <Form.Item { ...itemOptions } >{ children }</Form.Item>

const hidden = (isHidden) => {
  const type = typeof(isHidden);
  return (type === 'function' && isHidden()) || type === undefined || isHidden; 
    //默认是显示
}

class ItemLayout extends React.Component {
  render() {
    const { children } = this.props;
    return(
      <>
        {
          React.Children.map(
            children, (child, i) => {
              const { config: { isHidden, ...argv}} = child.props;
              return hidden(isHidden) ? null : //具有隐藏表单项能力
                  React.cloneElement(
                    <Layout { ...argv }>{ child }</Layout>,
                    {
                      ...children.props
                    }
                  )
            }
          )
        }
      </>
    )
  }
}

export default ItemLayout;
//config.js(配置文件)
import React from 'react';
import { Input } from 'antd';

export const formConfig = () => {
  return [
    {
      itemOptions : { //Form.Item的api配置
        label: '姓名'
        //...argv
      },
      name: 'username',
      initialValue: '',
      rules: [],
      children: <Input />
      //...argv
    },
    {
      itemOptions : {
        label: '密码'
      },
      name: 'password',
      initialValue: '',
      rules: [],
      children: <Input />,
      isHidden: true //隐藏此项 默认是显示
    },
    {
      itemOptions : {
        label: '密码'
      },
      name: 'password',
      initialValue: '',
      rules: [],
      children: <Input />,
      isHidden: () =>  false //通过方法来动态显示隐藏
    },
  ]
}

Support antd Formall api.

Why use the configuration file is a function of the form? Because the parameters of the function can be realized for transferring data between pages and profiles.

So use a page, the code is as follows

import React from 'react';
import { Form, Input } from 'antd';
import { formConfig } from './config.js';
import BaseItem from './BaseItem';
import ItemLayout from './ItemLayout';

@Form.create()
class MyTestForm extends React.Component {
  render() {
    const { form } = this.props;
    return(
      <Form>
        {
          formConfig().map((item, i) => 
             <ItemLayout><BaseItem key={i} config={item} form={form}/></ItemLayout>)
        }
      </Form>
    )
  }
}

export default MyTestForm;

Compared to traditional structures Form is not fast a lot, and page code level even more clearer.

note:

If you want to use a custom component (a personalized business component), the simple point I package for the Input

//自动trim的Input
import { Component } from 'react';
import { Input } from 'antd';

class TrimInput extends Component {
  handleChange = (e) => {
    e.target.value = e.target.value.trim();
    this.props.onChange(e.target.value); //Input Chang 后将值传递给props
  }

  render() {
    const { value, ...argv } = this.props;
    return(
      <Input
        value={ value } //将props的填在Input中
        { ...argv }
        onChange={this.handleChange}/>
    )
  }
}

export default TrimInput;

Business component needs to have the ability to customize the way data flows, the most important point is that when updates need to call this.props.onChange(data).

Search Form package SearchForm( )

If you feel this is not enough fun, then come together on BaseItemto re-package the business component of it. I believe everyone has a background search capabilities of it, then we packed a search SearchForm.

The increase is mainly a searchfunction of the value and pass out of form.

The main code is as follows:

//searchForm.js
import React from 'react';
import { Form, Button } from 'antd';

import BaseItem from './BaseItem';
import ItemLayout from './ItemLayout';

@Form.create()
class SearchForm extends React.Component {

  handleSearch = () => {
    const { form: { validateFields }, search } = this.props;
    validateFields((err, fieldsValue) => {
      console.log(fieldsValue);
      if(!err) {
        search && search(fieldsValue);
      }
    })
  }

  render() {
    const { form, searchConfig, search, form: { resetFields } } = this.props;
    return(
      <>
        <Form onSubmit={this.handleSearch}>
          {
            searchConfig().map((item, i) => 
               <ItemLayout><BaseItem key={i} config={item} form={form}/></ItemLayout>)
          }
          {
            search && <div>
              <Button htmlType="submit" type="primary" style={{marginRight: '20px'}}>
                  搜索
              </Button>
              <Button onClick={() => resetFields()}>重置</Button>
            </div>
          }
        </Form>
      </>
    )
  }
}

export default SearchForm;

Use the inside pages, single table or pumped into the profile uses:

//config.js 查询条件
export const searchConfig = () => {
  return [
    {
      itemOptions : {
        label: '条件一'
      },
      name: 'name1',
      initialValue: '',
      rules: [],
      children: <Input />
    },
    {
      itemOptions : {
        label: '条件二'
      },
      name: 'name2',
      initialValue: '',
      rules: [],
      children: <Input />
    }
  ]
}
import React from 'react';
import { searchConfig } from './config';
import SearchForm from './SearchForm';

class MyTestForm extends React.Component {
  handleSearch = value => {
    console.log(value);//获取到的查询条件
  }
  render() {
    return(
      <SearchForm searchConfig={searchConfig} search={this.handleSearch} />
    )
  }
}

export default MyTestForm;

Write queries like this form is not very fast Yeah, interrogated later on referring to this component, and then draw a profile, so OK.

There will often encounter this situation, pop inside Form, like this you need to pop to increase the capacity to collect data. We put the equivalent searchFormof components on Modal inside. Specific implementation code is not posted.

antd Form Several problems need attention.

  1. initialValue This property is just set the form of the initial value, when the need to dynamically change the value of the form of the time, use setFieldsValue

  2. resetFieldsThis property is a set of values and the reset state of the control input, (reset value initialValue, instead of clearing the data, the data needs to be emptied or used setFieldsValue)

antd Form New changes

antd FormIn the fourth version rc-field-form, but has not yet released, I saw on the 4.0-prepare branch.

There are two underlying components so what difference does it make?

First rc-field-formwill try to apibe consistent on the level, but there are still places made changes. Mainly the following points:

  • When not manually updated forms, we will not collect initialValuesvalue

    In rc-formwhich, if the user does not operate through a form, you will form from the initialValuescollection value. They think it's a bug, but a lot of users are using this, so they do not do repairs. In the rc-field-formmiddle, you will not have this bug. If you want to change the value of components used setFieldsValueinstead.

  • Instead of using an array of nested name string

    rc-formInside support user.namewill eventually be interpreted as{user:{ name: '' } }

    rc-field-formIt would be ['user', 'name']interpreted as {user: { name: '' }}and will user.nameexplain to become{ ['user.name']: ''}

  • Delete validateFieldsAndScrollthis property

    Because of the use findDomNode, but findDomNodein the StrictModemiddle it is marked as a warning. I think this is a form of excessive control components.

  • getFieldsError We will always return to the array

    rc-formWhen there is no wrong, it returns null, rc-field-formand now returns an empty array

  • Delete the validateFieldscallback function

    Because of ES8support async/await, there is no reason not to use it. When we use should be

    async function() {
      try {
        const values = await form.validateFields();
        console.log(values);
      } catch (errorList) {
        errorList.forEach(({ name, errors }) => {
          // Do something...
        });
      }
    }
  • setFieldsWill not trigger onFieldsChangeand setFieldsValuedo not triggeronValuesChange

    to sum up

This article is written own background most Form summary, as well as provide a way for everyone, the background of the rapid development of the way.

Will be updated later antd other components, how is the development of components more suitable for business scenes.

Guess you like

Origin www.cnblogs.com/zhuanzhuanfe/p/11696994.html