编写antd配置表单组件

编写antd配置表单组件

整体思路

  1. 抽取formitem的配置数组:包含组件类型、名称、label名称,相关的opts和扩展的opts,传递进入组件
  2. 组件通过Form.create()进行表单创建,能够带有form属性。并且上层组件引用后能够ref的方式获取form进行操作处理
  3. 基于form能够抽取出来,上层组件能够对下层组件进行调用和操作,在此基础上还能够进行扩展配置和扩展功能的实现
  4. 组件通过props中获取配置数组,动态生成FormItem的表单元素,实现动态配置表单的功能
  5. 组件通过在create中的mapPropsToFields中将外部对象数据data绑定到内部表单Item中了

实例实现代码,基于react和antd,类似的组件实现思路一致

组件js

import React, { PureComponent } from 'react';
import { Row, Form, Input, Col } from 'antd';
import FormItem from 'antd/lib/form/FormItem';
import BaseDataForm from '.';

// 通用组件
class _BaseDataForm extends PureComponent {

  // 默认属性
  defaultProps = {
    fields: [], // 外部传递进来的配置数据
  }

  state = {
  }

  getFromItems = () => {
    const { form } = this.props;
    const { getFieldDecorator } = form;
    const { fields, labelCol, wrapperCol } = this.props;
    const children = [];// 定义返回值数组
    const fieldsinput = fields || [];
    const labelColinput = labelCol || 7;
    const wrapperColinput = wrapperCol || 15;
    const formItemLayout = {
      labelCol: { span: labelColinput },
      wrapperCol: { span: wrapperColinput },
    };
    for (let index = 0; index < fieldsinput.length; index += 1) {
      const field = fieldsinput[index];
      let item = '';
      if (field.type === 'Input' || field.type === 'password') {
        // this.props.form.getFieldDecorator(id, options) 使用功能这个包装空间,id等于属性名
        item = getFieldDecorator(field.name, field.fieldDecoratorOps)(
          <Input {...field.elementOpts} />
        );
      }
      // 拼装表格
      children.push(
        <Col key={index}>
          <FormItem {...formItemLayout} label={field.label}>
            {item}
          </FormItem>
        </Col>
      );
    }
    return children;
  }

  render() {
    return (
      <Form>
        <Row>{this.getFields()}</Row>
      </Form>
    );
  }
}

导入js

// 经过Form.create包装过的组件会自带this.props.form
const BaseDataForm = Form.create({
  mapPropsToFields: (props) => {
    // 把父组件的属性映射到表单项上(如:把 Redux store 中的值读出),需要对返回值中的表单域数据用 Form.createFormField 标记,注意表单项将变成受控组件, error 等也需要一并手动传入
    const { fields = [], data = [] } = props;
    const values = {};
    fields.map(item => {
      const fieldName = item.name;
      let value = data[fieldName];
      if (fieldName.indexOf('.' !== -1)) {
        try {
          // eslint-disable-next-line no-eval
          value = eval('data.' + fieldName);
          // 特殊多层结构数据获取值
        } catch (error) {
          // eslint-disable-next-line no-console
          console.error(error);
        }
      }
      if (value !== undefined && value !== null) {
        // 特殊数据处理
      }
      values[fieldName] = Form.createFormField({ value });
      return item;
    });
    return values;
  },
})(_BaseDataForm);
export default BaseDataForm;

实例js

class Test extends PureComponent {

  exampleFields = [
    {
      type: 'Input',
      name: 'test',
      label: '输入1',
      fieldDecoratorOps: {}, // 表单绑定属性
      elementOpts: {}, // 标签属性
    },
    {
      type: 'Input',
      name: 'test2',
      label: '输入2',
      fieldDecoratorOps: {}, // 表单绑定属性
      elementOpts: {}, // 标签属性
    },
  ];

  saveFormRef = (form) => {
    this.form = from;
  }

  getFormData = () => {
    return this.form.getFieldsValue();
  }

  render() {
    return (
      <BaseDataForm
        ref={this.saveFormRef} // 通过ref将对应的表单from组件映射出来,能够直接调用
        data={{}} // data在创建表单的时候做了一次绑定,这个绑定能够将当前值显示进去
        fields={exampleFields}
      />
    );
  }
}
posted @ 2019-05-07 23:56  努力编程的小猪  阅读(2770)  评论(0编辑  收藏  举报