egg-validate 基于 parameter 的 eggjs 字段验证模块
egg-validate 是基于 parameter 的 eggjs 字段验证模块,可以验证我们日常开发中的大多数字段类型和数据,如果插件不满足你的需求,你还可以自定义验证规则。
安装
npm install --save egg-validate
启用
// config/plugin.js
exports.validate = {
enable: true,
package: 'egg-validate',
};
配置
// config/config.default.js
exports.validate = {
// convert: false,
// validateRoot: false,
};
使用方法
egg-validate 就是对参数进行检验。比如检验一个用户名是不是字符串,可以这么写:
ctx.validate({ userName: 'string' });
默认就会对 ctx.request.body 进行检验,你想检验 ctx.query 的话,那就这样写:
ctx.validate({ userName: 'string' }, ctx.query);
params 就 ctx.params,它会在检验失败的抛出一个异常,没有捕获的话,会返回一个 422 错误。
第二种使用方法:
let errs = app.validator.validate({ userName: 'string' }, ctx.request.body);
ctx.validate 检验不通过会抛出异常,而 app.validator.validate 检验不通过会返回错误。你可以自己选择要对这个错误怎么处理,是停止执行还是返回前端。
完整的代码
// app/controller/home.js
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
const { ctx, app } = this;
ctx.validate({ id: 'id' }); // will throw if invalid
// or
const errors = app.validator.validate({ id: 'id' }, ctx.request.body);
}
}
module.exports = HomeController;
校验规则 rule
完全和 parameter 的校验规则一样。建议直接看readme文档,虽然是英文的,但是配着翻译看个7788是差不多的。
ctx.validate({ userName: 'string' });
这里面的rule就是{ userName: 'string' },它会这么检验,首先判断这个userName有没有在ctx.request.body里面,没有就跑出参数不存在、然后是userName不能为空、然后得是string。有一个不符合都会抛出错误。
你想判断一个用户的信息是否正确可以这么写:
ctx.validate({
userName: 'userName', // 自定义的校验规则
password: 'password', // 自带的校验规则
sex: ['men', 'women'], // 性别是 men 或者 women
age: {
type: 'number', // 年龄范围0-120
min: 0,
max: 120
}
});
这里有个坑,年龄怎么填都会报格式错误,这是因为配置的时候默认把参数转型关了,配置回来就好:
config.validate = { // 配置参数校验器,基于parameter
convert: true, // 对参数可以使用 convertType 规则进行类型转换
// validateRoot: false, // 限制被验证值必须是一个对象。
};
使用自带的校验规则
password: 'password'
或者
password: {
type: 'password',
allowEmpty: true // 设置密码为空,作为示例乱写一下
}
校验规则有这些,文档很详细了:
'int'
=>{type: 'int', required: true}
'int?'
=>{type: 'int', required: false }
'integer'
=>{type: 'integer', required: true}
'number'
=>{type: 'number', required: true}
'date'
=>{type: 'date', required: true}
'dateTime'
=>{type: 'dateTime', required: true}
'id'
=>{type: 'id', required: true}
'boolean'
=>{type: 'boolean', required: true}
'bool'
=>{type: 'bool', required: true}
'string'
=>{type: 'string', required: true, allowEmpty: false}
'string?'
=>{type: 'string', required: false, allowEmpty: true}
'email'
=>{type: 'email', required: true, allowEmpty: false, format: EMAIL_RE}
'password'
=>{type: 'password', required: true, allowEmpty: false, format: PASSWORD_RE, min: 6}
'object'
=>{type: 'object', required: true}
'array'
=>{type: 'array', required: true}
[1, 2]
=>{type: 'enum', values: [1, 2]}
/\d+/
=>{type: 'string', required: true, allowEmpty: false, format: /\d+/}
自定义的校验规则
通过 app.validator.addRule 添加:
// 校验用户名是否正确
app.validator.addRule('userName', (rule, value)=>{ // value就是待检验的数据
if (/^\d+$/.test(value)) {
return "用户名应该是字符串";
}
else if (value.length < 3 || value.length > 10) {
console.log("用户名的长度应该在3-10之间");
}
});
这个可以直接放在 app.js 里面。return 的就是错误消息 message,但是 err 不止这个,还有错误字段啊啥的、都会帮我们自动包装好。
添加了这个规则就可以直接使用:
ctx.validate({userName: 'userName'});
或者这样使用:
ctx.validate({
userName: {
type: 'userName',
isAdmin: true'
},
});
直接赋值给 rule 传过来,然后你可以自己加判断,比如如果 isAdmin 的话,管理员用户名不能有中文啥的。
在哪里 addRule
上面写的是推荐大家在 app.js 里面 addRule,你可以在任何你能取到 app 的地方调用
app.validator.addRule('userName', (rule, value)=>{
去 addRule,但是不建议在 controller 里面 addRule。因为 controller 在每次路由匹配到之后都会进行实例化,所以请求了 n 遍,也就执行了这个 addRule n 遍。
而且代码会变的很臃肿,不易于管理。
在 app.js addRule 当然是很棒的,只在 app 加载时 add 一次。
但是问题又来了,随着 rule 变多,你在 app.js 里面写了很多代码都是关于 addRule 的,但是 app.js 又不止要写addRule,还写了一些别的,那看起来多乱啊。也不利于管理。
如何合理配置文件目录
我们希望能达到怎么样的一个效果呢?
- app.js 里面少写一些代码,最好就写一两行,做个配置这样子
- 对于所有的自定义校验规则独立出文件夹,取名 validate,放在 app/ 下面
- 针对相似的校验规则进一步抽象成文件,取名 user.js,放在 app/validate/ 下面
- 针对某一条特定的校验规则,如校验用户的 userName 放在 app/validate/user.js 里面
- 然后保持 egg-validate 的使用规则不变,原来是 ctx.validate 现在还是 ctx.vallidate。同时其他的插件、配置不受影响。
下面照着这几个目标实现代码
首先把 app.js 里面导入模块写出来
我们使用 Loader 来加载 validate 下面的所有文件:
const path = require('path');
module.exports = app => {
// 你的其它代码,balabala
// 加载所有的校验规则
const directory = path.join(app.config.baseDir, 'app/validate');
app.loader.loadToApp(directory, 'validate');
}
建立实际的校验规则文件
建立 app/validate/user.js 文件,写入以下代码
// app/validate/user.js
module.exports = app =>{
let { validator } = app;
// 校验用户名是否正确
validator.addRule('userName', (rule, value)=>{
console.log(rule);
if (/^\d+$/.test(value)) {
return "用户名应该是字符串";
}
else if (value.length < 3 || value.length > 10) {
console.log("用户名的长度应该在3-10之间");
}
});
// 添加自定义参数校验规则
validator.addRule('123', (rule, value) => {
if (value !== '123'){
return 'must be 123';
}
});
};
这里validator.addRule和原来一样,只是为了少写代码,之前把 validator 取出来了:
let { validator } = app;
之后需要再新建检验规则就写在 validate 里面,某一类相似校验规则要复用就直接拷贝文件就好了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论