JavaScript中setCustomValidity为何首次提交不显示,第二次才生效
问题根因
- 浏览器原生表单校验的执行顺序早于
onsubmit绑定的回调函数。第一次点击提交按钮时,浏览器会先执行默认校验逻辑,此时你还未调用setCustomValidity设置错误信息,浏览器判定表单校验通过,才会进入你自定义的validate函数。你在函数中设置完自定义错误后直接return false阻止了提交,但已经错过了本次的错误提示触发时机,因此第一次点击不会弹出提示。 - 第二次点击提交时,浏览器执行默认校验的阶段,上一次设置的自定义错误信息还残留在输入框的有效性状态中,因此会直接弹出上一次设置的提示,看起来就像是“第二次点击才生效”。
修复方法
需要做三处核心修改:
- 每次执行校验逻辑前,先清空两个输入框的自定义有效性状态,避免之前的错误提示残留影响后续校验
- 设置完自定义错误信息后,主动调用输入框的
reportValidity()方法触发错误提示弹出 - 所有校验通过时返回
true允许表单提交
修正后的JS代码
function validate(){ console.log("check validate()") const email = document.getElementById("email"); const psw = document.getElementById("psw"); // 先清空之前的自定义错误状态 email.setCustomValidity(""); psw.setCustomValidity(""); const emailReg = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; if (email.value === "" && psw.value === ""){ email.setCustomValidity("请输入邮箱和密码"); email.reportValidity(); // 主动触发错误提示 return false; } else if (email.value === ""){ email.setCustomValidity("请输入邮箱地址"); email.reportValidity(); return false; } else if (psw.value === ""){ psw.setCustomValidity("请输入密码"); psw.reportValidity(); return false; } else if (!emailReg.test(email.value)){ email.setCustomValidity("邮箱格式不正确"); console.log("邮箱格式校验不通过"); email.reportValidity(); return false; } // 所有校验通过,允许提交 return true; }
可选优化
可以给form标签添加novalidate属性,关闭浏览器默认校验逻辑,完全走自定义校验流程,避免原生校验和自定义校验的逻辑冲突:
<form onsubmit="return validate()" method="POST" action="login.php" novalidate> <input id="email" type="text" placeholder="邮箱"> <input id="psw" type="password" placeholder="密码"> <input type="submit" id="login-btn" value="登录"> </form>
内容的提问来源于stack exchange,提问作者wayta
相关产品推荐
相关产品推荐

