接入JS表单验证后Submit提交按钮无法正常提交表单问题排查
问题定位
你的表单点击提交无响应是3个核心问题导致的:
- 提交事件逻辑错误:你在submit监听回调的第一行就写了
e.preventDefault(),全局拦截了表单默认的提交行为,但是校验通过后的判断块是空的,没有编写任何提交表单的逻辑,等于不管校验是否通过,表单都不会向后端发送请求。 - HTML存在重复ID冲突:你给
<form>标签设置了id="apply",下方的提交按钮也设置了id="apply",JS中document.querySelector('#apply')只会选中页面里第一个出现的id=apply元素也就是提交按钮,给按钮绑定submit事件本身就不会生效,属于选择器匹配错误。 - 细节语法问题:姓、名两个输入框写了两个重复的id属性,同意条款的校验逻辑被注释,用户不勾选协议也能提交,注释掉的条款校验代码还存在未定义变量的bug。
修复方案
- 修正HTML的ID冲突:把提交按钮的ID改成其他值(比如
submitBtn),删掉输入框上重复的id属性。 - 调整JS提交逻辑:不要一进入事件回调就阻止默认提交,只有当所有字段校验不通过的时候才调用
e.preventDefault()拦截请求,校验通过直接走原生表单提交逻辑即可,不需要额外编写提交代码。 - 恢复同意条款的校验逻辑,补全之前代码里的变量定义错误。
修正后代码
HTML部分
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>DAS Applicant Form</title> <link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css"> </head> <body style="padding:40px"> <main> <h1>Applicant Form</h1> <div class="container"> <form action="create-lead.php" id="apply" class="form" method="POST"> <div class="form-field"> <label for="firstName">First Name</label> <input type="text" name="firstName" id="firstName"> <small></small> </div> <div class="form-field "> <label for="lastName">Last Name</label> <input type="text" name="lastName" id="lastName"> <small></small> </div> <div class="form-field"> <label for="email">Email</label> <input type="text" name="email" id="email"> <small></small> </div> <div class="form-field"> <label for="telephone">Telephone</label> <input type="text" name="telephone" id="telephone"> <small></small> </div> <label for="buyerType">Application Type</label> <select class="secondary" name="buyerType" id="buyerType"> <option value="Purchase">Purchase</option> <option value="FirstTimeBuyer">First Time Buyer</option> <option value="Remortgage">Remortgage</option> <option value="RaiseFunds">Raise Funds</option> </select> <div class="form-field"> <label for="accept"> <input type="checkbox" id="accept" name="accept" value="yes"> I agree to the terms and conditions <a href="#">See terms</a> </label> <small></small> </div> <div class="form-field"> <input class="outline " type="submit" name="appy" id="submitBtn"> <input class="outline secondary" type="reset" name="reset" id="reset"> </div> </form> </div> <script src="js/app.js"></script> </main> </body> </html>
JS部分
const firstNameEl = document.querySelector('#firstName'); const lastNameEl = document.querySelector('#lastName'); const emailEl = document.querySelector('#email'); const telephoneEl = document.querySelector('#telephone'); const acceptEl = document.querySelector('#accept'); const form = document.querySelector('#apply'); const checkFirstName = () => { let valid = false; const firstName = firstNameEl.value.trim(); if (!isRequired(firstName)) { showError(firstNameEl, 'First name cannot be blank'); } else if (!isFirstNameValid(firstName)) { showError(firstNameEl, 'First name must only contain letters'); } else { showSuccess(firstNameEl); valid = true; } return valid; }; const checkLastName = () => { let valid = false; const lastName = lastNameEl.value.trim(); if (!isRequired(lastName)) { showError(lastNameEl, 'Last name cannot be blank'); } else if (!isLastNameValid(lastName)) { showError(lastNameEl, 'Last name must only contain letters'); } else { showSuccess(lastNameEl); valid = true; } return valid; }; const checkEmail = () => { let valid = false; const email = emailEl.value.trim(); if (!isRequired(email)) { showError(emailEl, 'Email cannot be blank.'); } else if (!isEmailValid(email)) { showError(emailEl, 'Email is not valid.') } else { showSuccess(emailEl); valid = true; } return valid; }; const checkTelephone = () => { let valid = false; const telephone = telephoneEl.value.trim(); if (!isRequired(telephone)) { showError(telephoneEl, 'Telephone field cannot be left blank'); } else if (!isTelephoneValid(telephone)) { showError(telephoneEl, 'Number is not valid') } else { showSuccess(telephoneEl); valid = true; } return valid; }; const checkAccept = () => { let valid = false; if (!acceptEl.checked) { showError(acceptEl, 'You must accept the terms to continue') } else { showSuccess(acceptEl); valid = true; } return valid; }; const isFirstNameValid = (firstName) => { const re = /^[a-zA-Z]+$/; return re.test(firstName); }; const isLastNameValid = (lastName) => { const re = /^[a-zA-Z]+$/; return re.test(lastName); }; const isEmailValid = (email) => { const re = /^(([^<>()\[\]\\.,;:\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,}))$/; return re.test(email); }; const isTelephoneValid = (telephone) => { const re = /^[0-9]+$/; return re.test(telephone); }; const isRequired = value => value === '' ? false : true; const showError = (input, message) => { const formField = input.parentElement; formField.classList.remove('success'); formField.classList.add('error'); const error = formField.querySelector('small'); error.textContent = message; }; const showSuccess = (input) => { const formField = input.parentElement; formField.classList.remove('error'); formField.classList.add('success'); const error = formField.querySelector('small'); error.textContent = ''; } form.addEventListener('submit', function(e) { let isFirstNameValid = checkFirstName(), isLastNameValid = checkLastName(), isEmailValid = checkEmail(), isTelephoneValid = checkTelephone(), isAcceptValid = checkAccept(); let isFormValid = isFirstNameValid && isLastNameValid && isEmailValid && isTelephoneValid && isAcceptValid; if (!isFormValid) { e.preventDefault(); } }); const debounce = (fn, delay = 500) => { let timeoutId; return (...args) => { if (timeoutId) { clearTimeout(timeoutId); } timeoutId = setTimeout(() => { fn.apply(null, args) }, delay); }; }; form.addEventListener('input', debounce(function(e) { switch (e.target.id) { case 'firstName': checkFirstName(); break; case 'lastName': checkLastName(); break; case 'email': checkEmail(); break; case 'telephone': checkTelephone(); break; case 'accept': checkAccept(); break; } }));
内容的提问来源于stack exchange,提问作者Yenmangu
相关产品推荐
相关产品推荐

