动机
当我们使用 ElementUI 来做前端校验时,大多数项目都不会被其自带的简单校验规则所满足。所以我们经常需要自定义校验函数 validator 来满足我们的项目需求。而这时又会出现一个比较棘手的问题:这个自定义的 validator 由于无法传参,复用性极差。
比如我们上一篇文章做了一个自定义的中英文混合长度校验函数:
const validLength = function (rule, value, callback) {
function getStrLength(str) {
return str.replace(/[^x00-xff]/g, 'xxx').length;
}
if (!value) {
callback();
} else if (getStrLength(value) <= 64) {
callback();
} else {
return callback(new Error('不能超过 64 个字符'))
}
}
这时,有另一个表单想使用这个校验规则,但是要限制的长度不是 64 而是 128 。尴尬的事情发生了 —— 由于无法传参,我们要把这个校验函数再写一遍。如果还有 n 多个别的地方也想使用,我们是不是还要把这一串重复的代码写 n 遍呢?这显然不是开发者们想要的。
场景
当一套自定义校验规则适用于多个表单,只有参数不同时。
传参的实现
传参的目的无非是不同的调用者可以访问到不同的数据,所以当普通的传参无法实现时,我们改变了思路:使用 bind
。
原理:不用的调用者调用函数时,通过 bind 生成一个新的函数,并改变其 this 的指向。
这时,我们只需要在校验函数内部使用 this 来获取“参数”就好啦:
const validLength = function (rule, value, callback) {
function getStrLength(str) {
return str.replace(/[^x00-xff]/g, 'xxx').length;
}
if (!value) {
callback();
} else if (getStrLength(value) <= this.maxLength) {
callback();
} else {
return callback(new Error(`不能超过 ${this.maxLength} 个字符`))
}
}
const length32 = {
maxLength:32
}
const length64 = {
maxLength:256
}
使用时:
//...
rules:{
name:[{
validator: validLength.bind(length32),
trigger: 'blur'
}],
address:[{
validator: validLength.bind(length256),
trigger: 'blur'
}]
}
//...
如此一来,我们就使用了一套校验规则对多个表单进行了限制,并且达到了灵活的传参效果。