Ant Design表单实现

Ant Design表单实现

Posted by SkioFox on November 13, 2018

ant design 表单

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

function hasErrors(fieldsError) {
  return Object.keys(fieldsError).some(field => fieldsError[field]);
}

class HorizontalLoginForm extends React.Component {
  componentDidMount() {
    // To disabled submit button at the beginning.
    this.props.form.validateFields();
  }
 
  handleSubmit = e => {
    e.preventDefault();
    this.props.form.validateFields((err, values) => {
      if (!err) {
        console.log("Received values of form: ", values);
      }
    });
  };

  render() {
    const {
      getFieldDecorator,
      getFieldsError,
      getFieldError,
      isFieldTouched
    } = this.props.form;

    // Only show error after a field is touched.
    const userNameError =
      isFieldTouched("userName") && getFieldError("userName");
    const passwordError =
      isFieldTouched("password") && getFieldError("password");
    return (
      <Form layout="inline" onSubmit={this.handleSubmit}>
        <Form.Item
          validateStatus={userNameError ? "error" : ""}
          help={userNameError || ""}
        >
          {getFieldDecorator("userName", {
            rules: [{ required: true, message: "Please input your username!" }]
          })(
            <Input
              prefix={<Icon type="user" style= />}
              placeholder="Username"
            />
          )}
        </Form.Item>
        <Form.Item
          validateStatus={passwordError ? "error" : ""}
          help={passwordError || ""}
        >
          {getFieldDecorator("password", {
            rules: [{ required: true, message: "Please input your Password!" }]
          })(
            <Input
              prefix={<Icon type="lock" style= />}
              type="password"
              placeholder="Password"
            />
          )}
        </Form.Item>
        <Form.Item>
          <Button
            type="primary"
            htmlType="submit"
            disabled={hasErrors(getFieldsError())}
          >
            Log in
          </Button>
        </Form.Item>
      </Form>
    );
  }
}
const WrappedHorizontalLoginForm = Form.create({ name: "horizontal_login" })(
  HorizontalLoginForm
);

export default WrappedHorizontalLoginForm

表单实现

import React, { Component } from "react";
import { Icon } from "antd";

// HOC:包装用户表单,增加数据管理能力、校验
function kFormCreate(Comp) {
  return class NewComp extends Component {
    constructor(props) {
      super(props);
      this.options = {}; //字段选项设置
      this.state = {}; //各字段值
    }

    // 处理表单项输入事件
    handleChange = e => {
      const { name, value } = e.target;
      // setState是异步,在回调函数中去做校验
      this.setState(
        {
          [name]: value
        },
        () => {
          // 数值变化后再校验
          this.validateField(name);
        }
      );
    };

    // 表单项校验
    validateField = field => {
      const rules = this.options[field].rules;
      //只要任何一项失败就失败
      const ret = rules.some(rule => {
        if (rule.required) {
          //仅验证必填项
          if (!this.state[field]) {
            // 校验失败
            this.setState({
              [field + "Message"]: rule.message
            });
            return true; // 若有校验失败,返回true
          }
        }
      });
      if (!ret) {
        // 没失败,校验成功
        this.setState({ [field + "Message"]: "" });
      }
      return !ret;
    };

    // 校验所有字段(传入回调函数做校检)
    validate = cb => {
      // Object.keys()方法会返回一个由一个给定对象的自身可枚举属性组成的数组
      const rets = Object.keys(this.options).map(field =>
        this.validateField(field)
      );
      // 如果校验结果数组中全部为true,则校验成功
      const ret = rets.every(v => v === true);
      cb(ret);
    };
    // 利用HOC高阶组件对input组件进行封装扩展功能
    getFieldDec = (field, option, InputComp) => {
      // 保存配置项
      this.options[field] = option;
      // 返回包装后的input组件
      return (
        <div>
          {React.cloneElement(InputComp, {
            name: field, //控件name
            value: this.state[field] || "", //控件值
            onChange: this.handleChange, //change事件处理,在表单层级处理状态变化
            onFocus: this.handleFocus // 判断控件是否获得焦点, 在表单层级处理状态变化
          })}
          {/* {this.state[field + "Message"] && (
            <p style=>{this.state[field + "Message"]}</p>
          )} */}
        </div>
      );
    };

    //
    handleFocus = e => {
      const field = e.target.name;
      this.setState({
        [field + "Focus"]: true
      });
    };
    // 判断组件是否被用户点击过
    isFieldTouched = field => !!this.state[field + "Focus"];

    getFieldError = field => this.state[field + "Message"];

    render() {
      return (
        // 传递所有的属性
        <Comp
          {...this.props}
          getFieldDec={this.getFieldDec}
          value={this.state}
          validate={this.validate}
          isFieldTouched={this.isFieldTouched}
          getFieldError={this.getFieldError}
        />
      );
    }
  };
}
class FormItem extends Component {
  render() {
    return (
      <div className="formItem">
        {this.props.children}
        {this.props.validateStatus === "error" && (
          <p style=>{this.props.help}</p>
        )}
      </div>
    );
  }
}

class KInput extends Component {
  render() {
    return (
      <div>
        {/* 前缀图标 */}
        {this.props.prefix}
        <input {...this.props} />
      </div>
    );
  }
}
// 调用kFormCreate高阶组件包装KFormSample,高阶组件扩展了KFormSample的状态管理,数据管理
@kFormCreate
class KFormSample extends Component {
  onSubmit = () => {
    this.props.validate(isValid => {
      if (isValid) {
        alert("校验成功,提交登录");
        console.log(this.props.value);
      } else {
        alert("校验失败");
      }
    });
  };

  render() {
    // 接收通过属性传递的函数组件和属性
    const { getFieldDec, isFieldTouched, getFieldError } = this.props;

    const userNameError = isFieldTouched("uname") && getFieldError("uname");
    const passwordError = isFieldTouched("pwd") && getFieldError("pwd");

    return (
      <div>
        <FormItem
          validateStatus={userNameError ? "error" : ""}
          help={userNameError || ""}
        >
          {/* {封装input,扩展input功能} */}
          {getFieldDec(
            "uname",
            {
              rules: [{ required: true, message: "请填写用户名" }]
            },
            <KInput type="text" prefix={<Icon type="user" />} />
          )}
        </FormItem>
        <FormItem
          validateStatus={passwordError ? "error" : ""}
          help={passwordError || ""}
        >
          {getFieldDec(
            "pwd",
            {
              rules: [{ required: true, message: "请填写用户名" }]
            },
            <KInput type="password" prefix={<Icon type="lock" />} />
          )}
        </FormItem>

        <button onClick={this.onSubmit}>登录</button>
      </div>
    );
  }
}
// @kFormCreate不能和export default连用
// 实际导出的是经过kFormCreate包装的KFormSample
export default KFormSample;

利用高阶组件和属性传递不断对组件进行封装和扩展功能,利用状态提升在父级进行数据和状态管理