客户端验证报错时如何阻止jQuery点击事件触发服务端调用
问题原因
- 你的提交按钮加了
g-recaptcha类和data-callback属性,reCAPTCHA会自动接管按钮点击事件:点击后先做人机校验,通过就直接执行回调提交表单,优先级比你自己绑定的click事件高,所以你写的preventDefault()、return false根本拦不住提交动作。 - 之前绑定form的
submit事件后按钮失效,是因为reCAPTCHA生成的校验token是一次性的,上次校验失败后token已经作废,你没有重置reCAPTCHA状态,后续点击不会重新触发校验流程,按钮就没反应。 - 你的按钮是
type="button",本身不会触发表单默认提交,所有提交动作都是reCAPTCHA回调触发的,在按钮click事件里拦截自然卡不住提交链路。
修复步骤
1. 修改CSHTML里的提交按钮代码
去掉按钮上自动绑定reCAPTCHA的相关属性,不让reCAPTCHA自动接管点击:
@* 原来的按钮去掉g-recaptcha、data-sitekey、data-callback属性 *@ <input type="button" id="btn-submit" class="button u-mt--s ui-kit-button-medium" value="Send feedback"> <span class="button__text">Send Feedback</span>
reCAPTCHA组件本身保留@Display.Parts_Recaptcha()的渲染即可,不需要绑在按钮上。
2. 调整前端JS逻辑
把客户端校验放在最前面,校验通过后再手动触发reCAPTCHA校验,校验通过再提交表单,同时每次执行前清理旧错误、校验失败时重置reCAPTCHA状态:
// reCAPTCHA校验通过后的回调,执行表单提交 function rcCallback(token) { document.getElementById("feedback").submit(); } $("#btn-submit").on('click',function (e) { e.preventDefault(); const form = document.getElementById("feedback"); // 先清除上一次渲染的错误提示,避免重复叠加 const oldErrorTip = form.querySelector('.validation-summary-errors'); if(oldErrorTip) oldErrorTip.remove(); const validationerrors = document.createElement('div'); const ul = document.createElement('ul'); const span = document.createElement('span') validationerrors.className = "validation-summary-errors"; const validationErr = []; const emailValue = $('#email').val(); const name = $('#Name').val(); const comment = $('#Comment').val(); const aboutyourself = $('#AboutYourself').val(); const country = $('#country').val(); if (!name) validationErr.push("Your name is required"); if (!comment) validationErr.push("Your feedback is required"); if (!aboutyourself) validationErr.push("Your aboutyourself is required"); if (!emailValue) { validationErr.push("Your email address is required"); } else if (!validateEmail(emailValue)) { validationErr.push("Invalid Email Address"); } if (!country) validationErr.push("Your country is required"); if (validationErr.length > 0) { span.textContent = 'Your feedback was not submitted:'; validationerrors.append(span); validationErr.forEach(errMsg => { const li = document.createElement('li'); li.textContent = errMsg; ul.appendChild(li); }); validationerrors.append(ul); form.prepend(validationerrors); // 关键:校验失败重置reCAPTCHA状态,避免后续点击失效 grecaptcha.reset(); return false; } // 所有客户端校验通过后,再触发reCAPTCHA人机校验 grecaptcha.execute(); });
关键注意点
- 不要在form的
submit事件上做拦截,reCAPTCHA的提交是异步回调触发的,在按钮点击阶段先做业务校验,过了再走验证码流程链路最稳定。 - 每次校验失败必须调用
grecaptcha.reset(),否则上次的一次性token作废后,reCAPTCHA不会响应后续点击,就会出现按钮点不动的问题。 - 不要重复渲染错误提示,每次校验前先删掉旧的错误提示块,避免页面上出现多份重复的错误信息。
内容的提问来源于stack exchange,提问作者Ramji
相关产品推荐
相关产品推荐

