表单验证封装

439 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

以react项目antd组件库的使用为例

简单介绍rule规则

我们一般自定义rule的时候是这样的: 一个规则中一般必填之类的则,直接用,required,max,min等, 如果需要用正则,则可以用pattern等,

如果这样还无法满足验证的复杂度,就可以写validator作为自定义判断


<Form.Item
    name="checked"
    valuePropName="checked"
    rules={[
      {
        validator: (rule, value) => {
            if (value) {
              return Promise.resolve()
            }
            return Promise.reject(new Error("不能为空"));
        },
        message: '必选'
      },
    ]}
  >
    <Checkbox>
      <span className="receipt-footer-ok">
        我已阅读并同意...
    </Checkbox>
</Form.Item>

封装什么东西?

我们要把用正则写的,以及部分自定义的规则全部封装起来

那为什么要封装呢?

  1. 方便统一管理所有的正则和大部分自定义规则
  2. 可以复用规则
  3. 可以标准化message

开始封装

  1. 定义一下返回值

    首先明确我们这里需要的是一个函数,那么我们就写一个函数集合,,

export default {
    // mobile: (rule,value) => {
    //     return Promise.resolve();
    // }
}
  1. 先定义两组数据,正则和message
const _messages = {
  required: "必填",
  len: (value, count) => `请输入${count}位字符`,
  mobile: "请输入正确的手机号",
};

const isEmpty = (v) => {
  return typeof v == "undefined" || v === null || v === "";
};

const _rules = {
  required: (rule, value, callback) => {
    if (isEmpty(value)) {
      return false;
    }
    if (Array.isArray(value)) {
      if (str.length > 0) {
        return !value.some((item) => isEmpty(item));
      }
      return false;
    }
    return true;
  },
  mobile: (rule, value) => /^1[3|5|6|7|8|9|4][0-9]{9}$/.test(String(value)),

  len: (rule, value, count) => String(value).length === count,
};

export default {
    // mobile: (rule,value) => {
    //     return Promise.resolve();
    // }
}

  1. 像len和mobile这种表单,我们可以先让其验证必填,避免未填时验证格式
const addRequired = (rule, value, callback, _date) => {
  if (_rules.required(rule, value)) {
    return callback(rule, value, _data);
  }
};

const _rules = {
  required: (rule, value) => {
    if (isEmpty(value)) {
      return false;
    }
    if (Array.isArray(value)) {
      if (str.length > 0) {
        return !value.some((item) => isEmpty(item));
      }
      return false;
    }
    return true;
  },
  mobile: (rule, value) =>
    addRequired(rule, value, (rule, value) =>
      /^1[3|5|6|7|8|9|4][0-9]{9}$/.test(String(value))
    ),

  len: (rule, value, _data) =>
    addRequired(
      rule,
      value,
      (rule, value, count) => String(value).length === count,
      _data
    ),
};

  1. 把正则处理成返回值


function isFunction(obj) {
  return obj && typeof obj === "function";
}

const V = {};

Object.keys(_rules).forEach((name) => {
  V[name] = (rule, value) => {
    if (_rules[name](rule, value)) {
      return Promise.resolve();
    }
    return Promise.reject(
      isFunction(_messages[name]) ? _messages[name](value) : _messages[name]
    );
  };
});
export default V;


  1. 为了让参数传进来,定义一个函数。
const V = {
  transmit: (name, data) => {
    return (rule, value) => {
      if (_rules[name](rule, value, data)) {
        return Promise.resolve();
      }
      return Promise.reject(
        isFunction(_messages[name])
          ? _messages[name](value, data)
          : _messages[name]
      );
    };
  },
};

Object.keys(_rules).forEach((name) => {
  V[name] = (rule, value) => {
    if (_rules[name](rule, value)) {
      return Promise.resolve();
    }
    return Promise.reject(
      isFunction(_messages[name]) ? _messages[name](value) : _messages[name]
    );
  };
});

6.使用,两种使用,一种有参数,一种没有参数


 <Form.Item name="name" rules={[{ required: true, message: '请输入姓名' },{
    validator: Validator.transmit('len', 5)}]}>
    <Input placeholder="请输入手机号" />
  </Form.Item>
  
  
  <Form.Item name="phone" rules={[{ required: true, message: '请输入手机号' },{
    validator: Validator.mobile}]}>
    <Input placeholder="请输入手机号" />
  </Form.Item>