浏览器端和服务端都可以使用的验证器
发布于 7 年前 作者 hwen 3023 次浏览 来自 分享

最近基于自己的使用习惯和经验,写了个验证器。可以在浏览器端和 Node 环境下使用。

但这种验证器已经有非常多轮子了。。。没有特色是不行的。。。

这个验证器的特色:

1.内置规则以及可扩展规则

2.可以使用逻辑操作符

3.支持一组检验规则,哪里错误就提示那里

4.小巧并且可扩展,可以用多种形式封装。

5.单元测试 100% 覆盖绿

我自己就封装了个 forms-validator,本来还想用 vue 封装个的工具的,但没时间就暂时坑了

下面来简单介绍下,不过只介绍了部分功能。全部功能介绍,请看文档

问题

先考虑下下面的场景

1.我们要判断,一个小于20或者大于60同时还必须为素数的数字

2.校验邮箱地址

  • 当用户什么都没填,就点击提交时,提示他,‘邮箱必填’(‘Required…’)
  • 当用户填了些东西时,校验他是否是合法邮箱,并且是 Gmail 或者 QQ 邮箱,如果不是,点击提交时,提示‘邮箱格式有误’(‘Not a valid Email’)
  • 当用户邮箱填对了,并且是 Gmail 或者 QQ 邮箱了,校验他字符长度,不能超过32个字符。如果超过了,提示‘邮箱地址太长’(‘Email address too long’)

开始

先安装

npm i --save validator-core

然后

import Validator from 'validator-core'
const validator = new Validator()

内置规则以及可扩展规则

详细内置规则列表,见文档

  • 比如限定字串长度:
validator.test('1234', 'size:4') // => true
validator.test('12345', 'size:4') // => false
validator.test('1234', 'size:2-4') // => true
validator.test('1', 'size:2-4') // => false
validator.test(null, 'size:2-4') // => false
validator.test(123, 'size:2-4') // => false
  • 判断数字大小
validator.test(200, 'lt:400') // => true
validator.test(400, 'lte:400') // => true
validator.test(401, 'gt:400') // => true
  • 可扩展

比如这里我扩展了三条规则(合理扩展规则可以减少项目代码量)

使用validator.registerRules方法来进行扩展

  • ‘password’: 校验密码是非特殊字符,并且8到16位
  • ‘is_prime’: 判断数字是否为素数
  • ‘contain’: 判断字串是否包含另一个字串
const customRules = {
  'password': /^[^\s\u4E00-\u9FA5]{8,16}$/,
  'is_prime': function isPrimeNum (num, params) {
    if (params) console.log(params)
    if (typeof num !== 'number' || !Number.isInteger(num)) return false

    if (num === 2) {
      return true
    } else if (num % 2 === 0) {
      return false
    }

    const squareRoot = Math.sqrt(num)
    for (var i = 3; i <= squareRoot; i += 2) {
      if (num % i === 0) return false
    }

    return true
  },
  'contain': function (value, params) {
    if (!params) return false
    if (typeof value !== 'string') return false

    for (let i = 0; i < params.length; i++) {
      const item = params[i]
      if (value.indexOf(item) > -1) return true
    }
    return false
  }
}

validator.registerRules(customRules)

validator.test('abcd123', 'password') // => false
validator.test('abcd1234', 'password') // => true
validator.test(13, 'is_prime:just_test,hei')
// log: ['just_test', 'hei']
// => true
validator.test(24, 'is_prime') // => false

使用逻辑操作符

我们还是接上面的例子。可以使用的逻辑操作符有 &&, || 还有括号()

操作符不仅可以对内置规则使用,还可以对扩展的规则使用。还可以在一组校验规则时使用(合理运用会非常强大,下面例子会说到)。

比如说,

  • 我们要判断用户输入的邮箱(内置规则为email),是合法的,而且只支持 Gmail 和 QQ 邮箱,其他不支持
  • 我们要判断,一个小于20或者大于60同时还必须为素数的数字
validator.test('hwenleung@gmail.com', 'email && contain:gmail.com, qq.com') // => true
validator.test('hwenleung@163.com', 'email && contain:gmail.com, qq.com') // => false
validator.test('hwenleung@qq.com', 'email && contain:gmail.com, qq.com') // => true

validator.test(13, 'lt:20 || gt: 60 && is_prime') // => true
validator.test(23, 'lt:20 || gt: 60 && is_prime') // => false
validator.test(797, 'lt:20 || gt: 60 && is_prime') // => true

// 用括号来改变执行优先级
validator.test(4, 'lt:20 || (gt: 60 && is_prime)') // => true
validator.test(64, 'lt:20 || (gt: 60 && is_prime)') // => false
validator.test(797, 'lt:20 || (gt: 60 && is_prime)') // => true
validator.test(13, '((lt:20 || gt: 60) && is_prime)') // => true
validator.test(23, '((lt:20 || gt: 60) && is_prime)') // => false

支持一组检验规则,哪里错误就提示那里

继续接上面的例子。考虑以下情景:

我们有一个输入邮箱地址的输入框。

  • 当用户什么都没填,就点击提交时,提示他,‘邮箱必填’(‘Required…’)
  • 当用户填了些东西时,校验他是否是合法邮箱,并且是 Gmail 或者 QQ 邮箱,如果不是,提示‘邮箱格式有误’(‘Not a valid Email’)
  • 当用户邮箱填对了,并且是 Gmail 或者 QQ 邮箱了,校验他字符长度,不能超过32个字符。如果超过了,提示‘邮箱地址太长’(‘Email address too long’)

另外我还要校验一个价格,无论他有什么错我都提示,‘通用的错误提示’(‘Common Mes: Error occur’)

那么就可以用下面的代码来实现 (ruleSet)

注意,使用一组检验规则(ruleSet)时,要用validator.check而不是validator.test

test是对单个规则用的。

// ruleSet must be an Object Array
const ruleSet = [
  {
    name: 'Email', // rule should have a unique name
    // set of rules will be checked in order
    rules: ['required', 'email && contain:gmail.com, qq.com', 'size:32'],
    // tips are one-to-one of the rules, but you can set only one tip like 'Price'
    tips: ['Required...', 'Not a valid Email', 'Email address too long']
  },
  {
    name: 'Price',
    rules: ['required', 'lt:5000'],
    // 当错误消息只有一个时,会当成默认信息
    tips: ['Common Mes: Error occur']
  }
]

const validator = new Validator(ruleSet)
// or
// const validator = new Validator()
// validator.use(ruleSet)

console.log(validator.check('', 'Email'))
// => {isError: true, isPass: false, name: 'Email', tip: 'Required...'}
console.log(validator.check('some@some', 'Email'))
// => {isError: true, isPass: false, name: 'Email', tip: 'Not a valid Email'}
console.log(validator.check('Iamveryloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@gmail.com', 'Email'))
// => {isError: true, isPass: false, name: 'Email', tip: 'Email address too long'}
console.log(validator.check('hwenleung@gmail.com', 'Email'))
// => {isError: false, isPass: true, name: 'Email'}

最后

详细的文档及项目源码,在这里

如果有帮助的话,欢迎点个 star ~~

2 回复

亮点是支持逻辑运算符 :+1:。

可惜是AngularJs那一套,Javascript in Template。会制造各种魔符,IDE没有提示等等

现在流行的是 All in Javascript

这是我之前写的数据校验库struct,欢迎拍砖

const Struct = require('@axetroy/struct');

const data = {
  name: "axetroy",
  age: 18
};

const struct = new Struct({
  name: Struct.type.string,
  age: Struct.type.int
});

const err = struct.validate(data);

console.log(err); // undefined, because the data pass the validator

@axetroy (:з)∠) 大佬

回到顶部