# egg基于egg-validate的定制化升级
# 简单讲一下这个egg-validate
egg-validate是基于parameter的。安装:
npm install --save egg-validate
启用
// config/plugin.js
exports.validate = {
enable: true,
package: 'egg-validate',
};
2
3
4
5
配置
// config/config.default.js
exports.validate = {
// convert: false,
// validateRoot: false,
};
2
3
4
5
用途嘛,就是对参数进行检验。比如检验一个用户名是不是字符串,可以这么写,
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
校验不通过回返回错误。你可以自己选择要对这个错误怎么处理,是不管呢还是返回给前端。
# 关于校验规则rule
完全和parameter
的校验规则一样,建议看readme文档。
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
}
});
2
3
4
5
6
7
8
9
10
注意:这里有个坑,年龄怎么 填都会报格式错误,这是因为 配置的时候默认把参数类型转型关了,配置回来就好:
config.validate = { // 配置参数校验器,基于parameter
convert: true, // 对参数可以使用convertType规则进行类型转换
// validateRoot: false, // 限制被验证值必须是一个对象。
};
2
3
4
# 主要使用的几个点,核心使用
- 使用自带的校验规则:
password:‘password’,或者
password: {
type: 'password',
allowEmpty: true,
}
2
3
4
校验规则有这些,文档很详细了:
- 自定义的校验规则
通过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之间");
}
});
2
3
4
5
6
7
8
9
这个可以直接放在app.js里面。return的就是错误消息message,但是err不止这个,还有错误字段啊啥的、都会帮我们自动包装好。
- app.validator.addRule(‘userName‘, (rule, value)=>{里面这个字符串‘userName‘ 添加了这个规则就可以直接使用ctx.validate({userName: ‘userName‘});。 或者
ctx.validate({userName: {
type: 'userName',
isAdmin: true'
});
2
3
4
- app.validator.addRule(‘userName‘, (rule, value)=>{里面这个rule
像3、那样的规则就是把
{
type: 'userName',
isAdmin: true'
}
2
3
4
直接赋值给rule传过来
{ type: ‘userName‘, isAdmin: true }
然后你可以自己加判断,比如如果 isAdmin
的话,管理员用户名不能有中文啊,长度至少5位啊啥的。
- 在哪里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
里面手动拷贝吗。
所以下面接着讲eggjs
基于egg-validate
的定制化升级
# eggjs
基于egg-validate
的定制化升级
我们希望能达到怎么样的一个效果呢?
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');
}
2
3
4
5
6
7
8
9
10
# 然后建立实际的校验规则文件
建立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';
}
});
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
这样定制化升级就完成了。之后需要再新建检验规则就写在validate里面,某一类相似校验规则要复用就直接拷贝文件就好了。