Vue3+Element Plus提交时实现单次请求的异步表单验证
解决方案:单次请求完成所有字段验证
核心思路是区分「字段失焦验证」和「表单提交验证」:失焦时仍保持单个字段独立验证,提交时拦截字段级验证请求,合并为一次Precognition请求验证所有字段,再将结果分发到对应字段的验证回调中。
步骤1:改造验证函数,添加提交验证拦截逻辑
import { ref } from 'vue'; import type { InternalRuleItem, Value } from 'element-plus'; // 标记是否处于表单提交验证阶段 const isSubmittingValidation = ref(false); // 收集提交时需要验证的字段 const pendingFields = ref<string[]>([]); // 存储字段对应的验证回调 resolver const fieldResolvers = ref<Record<string, (success: boolean, msg?: string) => void>>({}); const validatePrecognitive = async (rule: InternalRuleItem, value: Value, callback: (error?: string | Error) => void) => { if (!rule.field) { callback(); return Promise.resolve(); } // 提交验证阶段:收集字段和回调,不单独发请求 if (isSubmittingValidation.value) { return new Promise((resolve) => { pendingFields.value.push(rule.field); fieldResolvers.value[rule.field] = (success, msg) => { success ? callback() : callback(new Error(msg)); resolve(); }; }); } // 失焦验证阶段:保留原单个字段验证逻辑 return new Promise<void>((resolve, reject) => { precognitive.post('/events', computedFormData.value, { validate: [rule.field], onPrecognitionSuccess(response) { if (response.status === 204) { callback(); resolve(); } }, onValidationError(response) { callback(new Error(response.data.message)); reject(); }, }); }); };
步骤2:编写全局表单提交验证函数
const validateFormOnSubmit = async () => { // 进入提交验证模式 isSubmittingValidation.value = true; pendingFields.value = []; fieldResolvers.value = {}; // 触发Element Plus表单验证,此时会收集所有待验证字段 await formEl.validate().catch(() => {}); // 去重待验证字段 const uniqueFields = [...new Set(pendingFields.value)]; if (uniqueFields.length === 0) { isSubmittingValidation.value = false; return true; } try { // 单次请求验证所有字段 await precognitive.post('/events', computedFormData.value, { validate: uniqueFields, onPrecognitionSuccess() { // 所有字段验证通过,触发所有字段的成功回调 Object.values(fieldResolvers.value).forEach(resolve => resolve(true)); }, onValidationError(response) { // 分发错误到对应字段 const errors = response.data.errors || {}; uniqueFields.forEach(field => { const errorMsg = errors[field]?.[0]; fieldResolvers.value[field]?.(!errorMsg, errorMsg); }); }, }); // 最终确认表单验证状态 const isValid = await formEl.validate(); isSubmittingValidation.value = false; return isValid; } catch (e) { isSubmittingValidation.value = false; return false; } };
步骤3:修改表单提交逻辑
提交时调用自定义的全局验证函数,而非直接调用formEl.validate():
const handleSubmit = async () => { const isValid = await validateFormOnSubmit(); if (isValid) { // 执行实际表单提交逻辑 // await submitFormData(); } };
保留原动态生成规则逻辑
字段失焦验证的规则无需修改:
const rules: FormRules = reactive({} as Partial<Record<string, Arrayable<FormItemRule>>>); Object.keys(getSubmitShape()).forEach(key => { rules[key] = [{ asyncValidator: validatePrecognitive, trigger: 'blur' }]; });
原理说明
- 状态标记区分场景:用
isSubmittingValidation标记当前是提交验证还是失焦验证,避免两种场景互相干扰。 - 收集请求统一处理:提交时先触发Element Plus的表单验证,收集所有待验证字段和对应的回调函数,再发起一次Precognition请求。
- 结果分发:根据后端返回的验证结果,调用对应字段的回调函数,通知Element Plus字段验证状态。
内容的提问来源于stack exchange,提问作者jacob_frankovic
相关产品推荐
相关产品推荐

