表单验证的三种方式

本文根据官方基本使用open in new window的示例代码展开。

根据内容所需增删后最终模板代码如下:

import { Form, Input, Button } from 'antd';

const Demo = () => {
  const onFinish = (values: any) => {
    console.log('Success:', values);
  };

  const onFinishFailed = (errorInfo: any) => {
    console.log('Failed:', errorInfo);
  };

  return (
    <Form
      name="basic"
      labelCol={{ span: 8 }}
      wrapperCol={{ span: 16 }}
      initialValues={{ remember: true }}
      onFinish={onFinish}
      onFinishFailed={onFinishFailed}
      autoComplete="off"
    >
      <Form.Item
        label="Username"
        name="username"
        rules={[{ required: true, message: 'Please input your username!' }]}
      >
        <Input />
      </Form.Item>

      <Form.Item
        label="Password"
        name="password"
        rules={[{ required: true, message: 'Please input your password!' }]}
      >
        <Input.Password />
      </Form.Item>

      <Form.Item
        label="Password"
        name="confirmPassword"
        rules={[{ required: true, message: 'Please input your password!' }]}
      >
        <Input.Password />
      </Form.Item>

      <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
      </Form.Item>
    </Form>
  );
};

ReactDOM.render(<Demo />, mountNode);

验证规则都在rules中配置,其类型是Rule[]open in new window。官网对Rule类型的解释是:

type Rule = RuleConfig | ((form: FormInstance) => RuleConfig);

但实际源码是:

type Rule = RuleObject | RuleRender

RuleObject就是Ruleopen in new window表格介绍中的内容,而RuleRender类型则是一个函数,其返回值还是一个RuleObject:

type RuleRender = (form: FormInstance) => RuleObject;

FormInstanceopen in new window的类型,通过这个对象解构出getFieldValue等获取字段值的方法。

了解了这些,只需记住想要实现表单数据验证,向Form.Item => rule提供RuleObjectRuleRender类型的验证参数即可。

1.使用RuleObject[]执行简单验证

在对单个字段进行较为简单的验证时,直接在rule上配置验证规则的对象数组即可:

import { Form, Input, Button } from 'antd';

const Demo = () => {
  return (
    <Form
      name="basic"
      labelCol={{ span: 8 }}
      wrapperCol={{ span: 16 }}
    >
      <Form.Item
        label="Username"
        name="username"
        rules={[
          { required: true, message: 'Please input your username!',type: 'string' },
          { min: 5, message: "位数需大于5" },
          { max: 20, message: "位数需小于20" },
        ]}
      >
        <Input />
      </Form.Item>
    </Form>
  );
};












 
 
 
 
 






2.使用validator函数增强验证

在只用RuleObject[]的方式无法满足验证需求时,可以在rule中配置一个含validator函数的对象即可,编写这个函数内容时,要么使用async返回一个promise,要么使用函数的第三个参数callback传出需要提示的错误信息。

validator重构验证:

import { Form, Input, Button } from 'antd';

const Demo = () => {
  return (
    <Form
      name="basic"
      labelCol={{ span: 8 }}
      wrapperCol={{ span: 16 }}
    >
      <Form.Item
        label="Username"
        name="username"
        rules={[
          { required: true, message: 'Please input your username!',type: 'string' },
          {
            // value 即是字段输入的内容
            validator(rule, value, callback) {
              if (value.length < 5) return callback("用户名长度不能小于5");
              if (value.length > 20) return callback("用户名长度不能大于20");
              callback();
            },
          }
        ]}
      >
        <Input />
      </Form.Item>
    </Form>
  );
};














 
 
 
 
 
 
 
 







如果使用的是typescript,直接在rule上定义validator函数可以正确获取类型提示。但有时候我们为了代码的简洁性,需要把这个函数提取出来,这时就没有直接的类型提示了,需要手动设置类型。

import { Form, Input, Button } from 'antd';
// 导入类型
import type { ValidatorRule } from "rc-field-form/lib/interface";

const Demo = () => {
    const usernameValidator: ValidatorRule = {
    // 由于参数2:value 有一个隐式 any 类型,所以需要手动设置其类型
    validator: (_, value: string, callback) => {
      if (/\W/.test(value)) return callback("不能出现字母数字下划线以外的字符");
      if (value.length < 3) return callback("用户名长度不能小于3");
      if (value.length > 10) return callback("用户名长度不能大于10");
      callback();
    },
  };

  return (
    <Form
      name="basic"
      labelCol={{ span: 8 }}
      wrapperCol={{ span: 16 }}
    >
      <Form.Item
        label="Username"
        name="username"
        rules={[
          { required: true, message: 'Please input your username!',type: 'string' },
          usernameValidator
        ]}
      >
        <Input />
      </Form.Item>
    </Form>
  );
};


 

 
 
 
 
 
 
 
 
 
 












 







提示

需要注意的是,从v4开始,validator的第三个参数callback已经被弃用,包括官方的例子里也没有再继续使用这个callback,现在推荐的做法是返回一个Promise

import { Form, Input, Button } from 'antd';
// 导入类型
import type { ValidatorRule } from "rc-field-form/lib/interface";

const Demo = () => {
  const usernameValidator: ValidatorRule = {
    validator: (rule, value) => {
      if (value) {
        if (/\W/.test(value)) return Promise.reject('用户名只能是字母数字下划线');
        if (value.length < 3) return Promise.reject("用户名长度不能小于3");
        if (value.length > 10) return Promise.reject("用户名长度不能大于10");
      }
      return Promise.resolve("");
    }
  };

  return (
    <Form
      name="basic"
      labelCol={{ span: 8 }}
      wrapperCol={{ span: 16 }}
    >
      <Form.Item
        label="Username"
        name="username"
        rules={[
          { required: true, message: 'Please input your username!',type: 'string' },
          usernameValidator
        ]}
      >
        <Input />
      </Form.Item>
    </Form>
  );
};








 
 
 
 
 






















3.使用RuleRender函数增强验证

使用RuleRender函数不仅仅可以验证当前字段的内容,还可以通过参数中提供的函数(比如:getFieldValue)等进行多字段数据的对比校验。使用较多的案例是密码的二次校验

import { Form, Input, Button } from 'antd';
// 导入类型
import type { RuleRender } from "rc-field-form/lib/interface";

const Demo = () => {
    const confirmPassword: RuleRender = ({ getFieldValue }) => ({
    validator(_, value) {
      if (!value || getFieldValue("password") === value) {
        return Promise.resolve();
      }
      return Promise.reject("两次密码不一致");
    },
  })

  return (
    <Form
      name="basic"
      labelCol={{ span: 8 }}
      wrapperCol={{ span: 16 }}
    >
      <Form.Item
        label="Password"
        name="password"
        rules={[{ required: true, message: 'Please input your password!' }]}
      >
        <Input.Password />
      </Form.Item>

      <Form.Item
        label="Password"
        name="confirmPassword"
        rules={[
          { required: true, message: 'Please confirm your password!' },
          confirmPassword,
        ]}
      >
        <Input.Password />
      </Form.Item>
    </Form>
  );
};


 


 
 
 
 
 
 
 
 




















 







注:rule配置多个验证规则都是可以一起工作的。另外,usernameValidatorconfirmPassword是不一样的,前者是一个对象,后者是一个函数。

最近更新:
Contributors: untilthecore