随便写写之 schema-typed 做表单数据验证

3,322 阅读2分钟

在一些 Web 应用中,表单处理起来比其他功能模块都麻烦,很多体力活,往往在数据的校验会很费时间,自从我用了schema-typed (github.com/rsuite/sche… 这个工具,发现很多场景变得异常简单。

安装

npm install schema-typed --save

示例

import { SchemaModel, StringType, DateType, NumberType, ObjectType, ArrayType } from 'schema-typed';
const model = SchemaModel({
  username: StringType().isRequired('Username required'),
  email: StringType().isEmail('Email required'),
  age: NumberType('Age should be a number').range(18, 30, 'Over the age limit'),
  tags: ArrayType().of(StringType('The tag should be a string').isRequired()),
  role: ObjectType.shape({
    name: StringType().isRequired('Name required'),
    permissions: ArrayType().isRequired('Permissions required')
  })
});
const checkResult = model.check({
  username: 'foobar',
  email: 'foo@bar.com',
  age: 40,
  tags: ['Sports', 'Games', 10],
  role: { name: 'administrator' }
});
console.log(checkResult);

示例代码的返回结构如下:

{
  username: { hasError: false },
  email: { hasError: false },
  age: { hasError: true, errorMessage: 'Over the age limit' },
  tags: {
    hasError: true,
    array: [
      { hasError: false },
      { hasError: false },
      { hasError: true, errorMessage: 'The tag should be a string' }
    ]
  },
  role: {
    hasError: true,
    object: {
      name: { hasError: false },
      permissions: { hasError: true, errorMessage: 'Permissions required' }
    }
  }
};

数据多重验证

StringType()
  .minLength(6, "Can't be less than 6 characters")
  .maxLength(30, 'Cannot be greater than 30 characters')
  .isRequired('This field required');

数据自定义验证

我们可以通过一个 addRule 函数来自定义某些规则;还可以通过 pattern 方法设置一个正则表达式进行自定义验证

const model = SchemaModel({
  field1: StringType().addRule((value, data) => {
    return /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(value);
  }, 'Please enter legal characters'),
  field2: StringType().pattern(/^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/, 'Please enter legal characters')
});
model.check({ field1: '', field2: '' });

/**
{
  field1: {
    hasError: true,
    errorMessage: 'Please enter legal characters'
  },
  field2: {
    hasError: true,
    errorMessage: 'Please enter legal characters'
  }
};
**/

数据多字段交互验证

如下例子是用来验证两个密码是否一致

const model = SchemaModel({
  password1: StringType().isRequired('This field required'),
  password2: StringType().addRule((value, data) => {
    if (value !== data.password1) {
      return false;
    }
    return true;
  }, 'The passwords are inconsistent twice')
});

model.check({ password1: '123456', password2: 'root' });

/**
{
  password1: { hasError: false },
  password2: {
    hasError: true,
    errorMessage: 'The passwords are inconsistent twice'
  }
}
**/

异步检查

如下例子用来验证邮箱是否重复

function asyncCheckEmail(email) {
  return new Promise(resolve => {
    setTimeout(() => {
      if (email === 'foo@domain.com') {
        resolve(false);
      } else {
        resolve(true);
      }
    }, 500);
  });
}

const model = SchemaModel({
  email: StringType()
    .isEmail('Please input the correct email address')
    .addRule((value, data) => {
      return asyncCheckEmail(value);
    }, 'Email address already exists')
    .isRequired('This field cannot be empty')
});

model.checkAsync({ email: 'foo@domain.com' }).then(checkResult => {
  console.log(checkResult);
  /**
  {
    email: {
      hasError: true,
      errorMessage: 'Email address already exists'
    }
  };
  **/
});

验证嵌套对象

验证嵌套对象,这些对象可以使用ObjectType()方法定义。例如:

const model = SchemaModel({
  id: NumberType().isRequired('This field required'),
  name: StringType().isRequired('This field required'),
  info: ObjectType().shape({
    email: StringType().isEmail('Should be an email'),
    age: NumberType().min(18, 'Age should be greater than 18 years old')
  })
});

const user = {
  id: 1,
  name: '',
  info: { email: 'schema-type', age: 17 }
};

model.check(data);

/**
 {
  "id": { "hasError": false },
  "name": { "hasError": true, "errorMessage": "This field required" },
  "info": {
    "hasError": true,
    "object": {
      "email": { "hasError": true, "errorMessage": "Should be an email" },
      "age": { "hasError": true, "errorMessage": "Age should be greater than 18 years old" }
    }
  }
}
*/

组合校验

SchemaModel提供了一个静态方法组合,可以与多个SchemaModel组合,以返回一个新的SchemaModel。

const model1 = SchemaModel({
  username: StringType().isRequired('This field required'),
  email: StringType().isEmail('Should be an email')
});

const model2 = SchemaModel({
  username: StringType().minLength(7, "Can't be less than 7 characters"),
  age: NumberType().range(18, 30, 'Age should be greater than 18 years old')
});

const model3 = SchemaModel({
  groupId: NumberType().isRequired('This field required')
});

const model4 = SchemaModel.combine(model1, model2, model3);

model4.check({
  username: 'foobar',
  email: 'foo@bar.com',
  age: 40,
  groupId: 1
});

常用的API

具体详细用法可以参照资料:github.com/rsuite/sche…

  • SchemaModel
  • StringType
  • NumberType
  • ArrayType
  • DateType
  • ObjectType
  • BooleanType