VUE3+elementPlus 之 Form表单校验器 之 数字类型、小数位数校验

限制录入数字类型+小数位数限制:

封装自定义验证器:

/**
 * 数字输入项校验
 * @param {*} rule         element-ui 表单校验规则
 * @param {*} value        输入项的值
 * @param {*} callback     回调函数
 * @param {*} extraInfo    附加校验信息:
 * allowZero  boolean 是否允许为0,true:允许
 * isRate     boolean 是否是百分比字段,true:是
 * numRange   object  数字允许范围(min最小值,max最大值)
 * numDecimal integer 数字小数位数
 * fieldName  string  字段中文名称
 */
export function validNumField(rule: any, value: any, callback: any, extraInfo: any) {
  value = value ? `${value}`.trim() : "";

  if (!value) {
    callback();
    return;
  }

  if (!extraInfo?.allowZero && value === "0") {
    callback(new Error("请输入非0数字"));
    return;
  }

  if (!isNumber(value)) {
    callback(new Error("请输入数字"));
    return;
  }

  if (
    extraInfo?.numRange &&
    !checkNumberRange(value, extraInfo?.numRange.min, extraInfo?.numRange.max)
  ) {
    const suffix = extraInfo.isRate ? "%" : "";
    const msg = `${extraInfo?.numRange.min}${suffix} ~ ${extraInfo?.numRange.max}${suffix}`;
    callback(new Error(msg));
    return;
  }
  if (extraInfo.numDecimal) {
    if (getDecimal(value) > extraInfo?.numDecimal) {
      callback(new Error(`小数点后限 ${extraInfo.numDecimal}`));
      return;
    }

    if (value.includes(".") && !value.split(".")[1]) {
      callback(new Error("请补全小数点后数字"));
      return;
    }
  } else {
    if (value.includes(".")) {
      callback(new Error("请输入整数"));
      return;
    }
  }

  callback();
}

/**
 * 检查是否为数字
 * @param String | Number value     待检测数值
 * @returns
 */
export function isNumber(value: any) {
  if (value === "" || value === null) {
    return false;
  }
  //对于空数组和只有一个数值成员的数组或全是数字组成的字符串,
  //isNaN返回false,例如:'123'、[]、[2]、['123'],isNaN返回false,
  if (!isNaN(value) && ["bigint", "number", "string"].includes(typeof value)) {
    return true;
  }

  return false;
}

/**
 * 校验数字范围
 * @param {*} num
 * @param {*} min
 * @param {*} max
 * @returns
 */
export function checkNumberRange(num: any, min: any, max: any) {
  if (num === null) {
    //未输入,不校验
    return true;
  }

  let _num = num;
  if (checkSafeInt(num)) {
    _num = parseFloat(num);
    if (isNaN(_num)) {
      //非数字,校验失败
      return false;
    }
  }
  if (numCompare(_num, min) < 0) {
    return false;
  }
  if (numCompare(_num, max) > 0) {
    return false;
  }
  return true;
}

/**
 * 兼容浮点数的数字大小比较
 * @param {*} num1
 * @param {*} num2
 * @returns 1:num1 大于 num2; 0:num1 等于 num2; -1:num1 小于 num2
 */
export function numCompare(num1: any, num2: any) {
  let arg1 = filtNumber(num1);
  let arg2 = filtNumber(num2);
  const decimal1 = getDecimal(arg1);
  const decimal2 = getDecimal(arg2);
  const maxDecimal = getMaxDecimal(decimal1, decimal2);

  if (checkSafeInt(arg1) && checkSafeInt(arg2)) {
    const multiples = Math.pow(10, maxDecimal);
    arg1 = parseFloat(arg1) * multiples;
    arg2 = parseFloat(arg2) * multiples;

    if (arg1 > arg2) {
      return 1;
    }
    if (arg1 === arg2) {
      return 0;
    }
    return -1;
  }

  const _arg1 = new Decimal(arg1);
  const _arg2 = new Decimal(arg2);
  return _arg1.comparedTo(_arg2);
}

组件内使用:

const extraInfo = {
  numRange: {
    min: 0,
    max: 999,
  },
  numDecimal: 4,
};
const validNumerField = (rule: any, value: any, callback: any) => {
  validNumField(rule, value, callback, extraInfo);
};
rules: {
	weight: [{ validator: validNumerField }]
}

页面效果:
非数字:
在这里插入图片描述
小数点后无内容:

在这里插入图片描述
超过限制小数位数:
在这里插入图片描述
超过最大值:
在这里插入图片描述

你可能感兴趣的:(vue,web前端,elementui,vue.js,前端,javascript)