Skip to content
Ya Hui Liang(Ryou) edited this page May 24, 2021 · 1 revision

更加简单易用的JS校验库

slime-validator是一个结合目前主流校验库能力,集各家所长,并提供更加简单易用的校验能力。相比其他库可以节约校验相关代码量20%左右,在复杂参数校验的情况下甚至能达到30%以上(这里是单纯的指代码字母总数量对比)。并且支持字段联动校验,因此你也可以通过slime-validator更加复杂的校验功能,这是其它校验库很少支持的能力。尤其是validatorjs,往往需要自己重新封装。

  • 关于字段联动校验可以参看文末的例子。

如何使用

slime-validator可以应用于后端,也可以应用于前端,但是最初设计是针对后端设计的,因为前端绝大多数情况下都是直接使用antd或者elementUI,而它们都内置校验库,所以没有太大必要使用slime-validator

安装

  $ npm i slime-validator -save

当然也提供了通过script标签直接引入的方式,但是由于没有发布CDN。需要自行解决引入源的问题。

如何使用

slime-validator有两种校验方法,一种是每次创建一个Validator对象。这样可以重复使用这个对象直接对参数进行预期规则的校验。另一种是通过Validator.validate函数,通过传入校验规则和待校验对象进行校验。和其他校验库用法类似。

  import Validator from 'slime-validator'

  // 用法一
  const V1 = new Validator({ Required:true })
  console.log(V1.validate('Hello world')) // 输出: null
  console.log(V1.validate()) // 输出: Input is required

  // 用法二
  console.log(Validator.validate({ Required:true }, 'Hello world')) // 输出: null
  console.log(Validator.validate({ Required:true }, null)) // 输出: Input is required

如何校验一个对象参数

校验对象,是校验非常普遍的一个需求场景。slime-validator自然而然也必须支持这个能力。

  import Validator from 'slime-validator'

  // 校验一个对象
  const V2 = new Validator({
    username: { Required: true, MinLength: 3 }, // 用户名必填,且不小于3个字符
    age: { Required: true, MinNum: 18 }, // 年龄必填,且需要大于18岁
    address: { MaxLength: 10 } // 地址选填,最大不超过10个字
  })
  console.log(V2.validate({
    username: 'ryouaki',
    age: 17
  })) // 输出:{ age: 'Min value of age is 18' }
  • 也可以直接使用Validator.validate来校验。

如何校验一个嵌套对象

在复杂的业务场景,我们需要校验的对象会非常复杂,这个时候,对于像validatorjs就要额外封装才能满足需要,而async-validator一样需要用一些额外字段去识别这是什么类型的待校验对象。

但是在slime-validator中,只需要一个$fields字段就完成了所以功能,在内部会自动识别对象还是数据还是对象加数组,因此开发者可以少书写很多代码。校验的对象越复杂,收益越明显。

  // 校验一个嵌套对象
  const V3 = new Validator({
    person: {
      $fields: {
        height: { Required: true },
        age: { Required: true },
        weight: { Required: true }
      }
    }
  })
  console.log(V3.validate({
    person: {
      height: 175,
      age: 18
    }
  })) // 输出:{"person":{"weight":"weight is required"}}

  // 校验一个嵌套数组
  const V4 = new Validator({
    persons: {
      MinLength: 2,
      $fields: {
        name: { Required: true }
      }
    }
  })
  console.log(V4.validate({
    persons: []
  })) // 输出:{"persons":"Min length of persons is 2"}
  console.log(V4.validate({
    persons: [{},{name: "太君是我,别开枪"},{}] // 索引1的元素有name所以错误信息是null
  })) // 输出:{"persons":[{"name":"name is required"},null,{"name":"name is required"}]}
  • 也可以直接使用Validator.validate来校验。

  • 在这里,当待校验对象是一个数组的时候,返需要用填充null来弥补占位,而其它可以参考的库在这块支持相对较弱,所以,目前也没有一个比较好的Idea。

如何自定义信息和校验规则

通常,虽然校验规则是一样的,但是提示信息可能不一样,或者在大部分情况下提示信息是一样的,但是校验规则可能略有不同。这个时候我们可以通过传入messagevalidate两个参数来针对性修改。

  // 使用自定义消息覆盖规则默认消息
  const V5 = new Validator({
    field: {Required: true, message: '我是消息'}
  })5
  console.log(V5.validate({
  })) // 输出:{ field: '我是消息' }

  // 使用自定义规则覆盖默认规则
  const V6 = new Validator({
    field: {Required: true, validate(field, value, opts) {
      return false // 永远校验失败
    }}
  })
  console.log(V6.validate({
    field: "我有数据"
  })) // 输出:{ field: 'field is required' }
  • 也可以直接使用Validator.validate来校验。

关于自定义扩展

默认提供的校验规则往往很难满足所有业务场景,而且在具体的业务处理过程中,也希望有一些规则可以被反复的复用。因此slime-validator提供了插件的能力,一旦注册插件,即可在全局使用该规则。这就像Vueplugin是一样的。只要use一个组件以后,在任何地方都可以直接使用了。

  // 自定义校验规则插件
  Validator.usePlugin({
    tagName: 'IsNotRequired',
    message(field, value, opts) {
      // field为校验的字段名,value为当前字段的值,opts为附加信息,包括tagName,当前规则名,tagValue当前规则的值,root,校验对象,parent,当前校验值的上一级父对象。
      return `${field} 校验不通过`
    },
    validate(field, value, opts) {
      return false
    }
  }, true) // 通过第二个参数传入true可以覆盖目前系统中已经注册的同名校验规则。

  const V7 = new Validator({
    field: { IsNotRequired: true }
  })
  console.log(V7.validate({
    field: "我有数据"
  })) // 输出:{ field: 'field 校验不通过' }
  • 也可以直接使用Validator.validate来校验。

联动校验

根据不同的国家,选择不同的类型进行联动校验。

  // type_rules.js
  import Validator from 'slime-validator';

  Validator.usePlugin({
    tagName: "CheckType", // 注册一个CheckType校验规则
    message(field, value, opts) {
      const { tagValue, parent } = opts; // 通过parent 我们可以很容易拿到依赖的父级对象。
      return `当前值为 ${value} 有效值为 ${tagValue[parent.country]}`
    },
    validate(field, value, opts) {
      const { tagValue, parent } = opts;
      return tagValue[parent.country].indexOf(value) > -1 
    }
  })

  // TypeController.js
  const rules = {
    country: {
      Required: true,
      Enum: ["CN", "USA", "JP"], message: "国家内容类型不正确" // 国家字段只能是"CN", "USA", "JP"其中之一。
    },
    type: { Required: true,  CheckType: {
      CN: [1, 3],
      USA: [1, 2, 3],
      JP: [2, 3]
    }}
  }

  const V = new Validator(rules);

  // CN
  console.log("CN", JSON.stringify(Validator.validate(rules, {
    country: "CN",
    type: 1
  })))
  console.log("CN", JSON.stringify(V.validate({
    country: "CN",
    type: 2
  })))

  // USA
  console.log("USA", JSON.stringify(Validator.validate(rules, {
    country: "USA",
    type: 1
  })))
  console.log("USA", JSON.stringify(V.validate({
    country: "USA",
    type: 2
  })))

  // JP
  console.log("JP", JSON.stringify(Validator.validate(rules, {
    country: "JP",
    type: 1
  })))
  console.log("JP", JSON.stringify(V.validate({
    country: "JP",
    type: 2
  })))
  • 如果使用new Validator的方式代码量会更少,所以还是推荐使用对象的方式使用。
  $ CN null
  $ CN {"type":"当前值为 2 有效值为 1,3"}
  $ USA null
  $ USA null
  $ JP {"type":"当前值为 1 有效值为 2,3"}
  $ JP null

更多的内置校验规则

Required 必填

进行必填校验,值为true或者false

  { Required: true }

Enum 枚举校验

校验值是否为枚举范围内的值,值为包含基础数据类型的数组,内部是通过值比较实现的。

  { Enum: [0, 1, 2, 3] }

NotEmpty 非空校验

判断待校验对象是否为空,支持字符串,数组,对象的校验,值为true或者false

  { NotEmpty: true }

MaxLength 和 MinLength

最大长度和最小长度校验,支持数组,字符串,值为数字。

  { MinLength: 1, MaxLength: 10 }

MaxNum 和 MinNum

最大数值和最小数值校验,值为数字。

  { MinLength: 1, MaxLength: 10 }

RegExp 正则校验

正则匹配校验,值为正则对象或者正则字符串。

  { RegExp: /^a/g }
  { RegExp: '^a' }