在日常开发中,我们常常需要在表单中对用户输入进行接口校验。比如,某个输入框输入完成后,需要调用接口判断是否合法,再决定是否获取联动数据。
本文将围绕以下业务场景,深入讲解如何正确使用 validator 配合节流/防抖和异步接口校验,避免校验失效的问题。
1、业务场景说明
一个输入框(或下拉框),用户输入后需要:
- 调用接口校验输入值是否合法;
- 若合法,继续调用另一个接口获取后续联动数据;
- 并且,该输入框是被其他表单项依赖的,需要及时触发校验和数据更新。
初始方案:使用 blur 触发校验
{ validator: validatePass2, trigger: 'blur' }
这在大多数表单项中是常规写法。用户输入完成后失焦,触发 validatePass2 方法,完成接口验证。
问题: 如果该字段被其他字段依赖,用户不失焦就不会触发校验,从而影响联动逻辑。
改进方案:使用 change 触发
{ validator: validatePass2, trigger: 'change' }
这样一旦输入变化就触发校验,可以即时联动。
新问题来了:
- 只要用户输入,就会不断触发接口请求;
- 输入较快时频繁请求,接口压力变大,性能下降。
进一步优化:引入节流或防抖
{ validator: debounce(validatePass2, 500), trigger: 'change' }
const validatePass2 = debounce((rule, value, callback) => {
// 异步请求
}, 500)
这边不知道为什么第二种不可以,有知道的大佬看回复一下
校验失效:async/await + validator 的陷阱
const validatePass2 = async (rule, value, callback) => {
const res = await apiValidate(value);
if (res.valid) {
callback();
} else {
callback(new Error('输入不合法'));
}
}
看起来没问题,但有些场景下表单项永远处于“校验中”状态,或者根本不触发 callback,直接导致表单验证失败或失效。
const validatePass2 = (rule, value, callback) => {
apiValidate(value).then(res => {
if (res.valid) {
callback();
} else {
callback(new Error('输入不合法'));
}
}).catch(() => {
callback(new Error('验证失败'));
});
}
最后只能修改成这样子
欢迎大家留言探讨你们的实践经验,如有疏漏或不妥之处,欢迎在评论区指出,互相学习,共同进步!