JavaScript表单验证后无法重新提交问题咨询
表单验证后无法重新提交的解决方法
问题根源
你的代码存在两个核心问题导致修正错误后无法重新提交:
- 状态类管理混乱:
showError直接替换父元素类名,showSuccess仅添加成功类,导致字段的错误/成功状态无法被正确覆盖或清除。 - 无提交放行逻辑:每次提交都用
e.preventDefault()阻止默认行为,哪怕所有字段验证通过,也不会触发表单的真正提交。
修复方案
1. 统一字段状态重置逻辑
修改showError和showSuccess函数,先清除旧状态再添加新状态:
// 显示错误信息 function showError(input, message) { const formControl = input.parentElement; formControl.classList.remove("success"); formControl.classList.add("error"); const small = formControl.querySelector("small"); small.innerText = message; } // 显示成功状态 function showSuccess(input) { const formControl = input.parentElement; formControl.classList.remove("error"); formControl.classList.add("success"); }
2. 添加验证通过后的提交放行逻辑
在提交事件中,先执行所有验证,再检查是否存在错误字段,仅当无错误时才允许表单提交:
form.addEventListener("submit", (e) => { // 重置所有字段的状态和提示文本 const allInputs = [P_FirstName, P_LastName, P_Email, P_PhoneNum, ParentID, Password]; allInputs.forEach(input => { const formControl = input.parentElement; formControl.classList.remove("error", "success"); formControl.querySelector("small").innerText = ""; }); // 执行所有验证规则 checkRequired(allInputs); checkLength(Password, 8, 25); checkFirstName(P_FirstName); checkLastName(P_LastName); checkEmail(P_Email); checkPhoneNumber(P_PhoneNum); checkUserName(ParentID); checkPassword(Password); // 判断是否存在错误字段 const hasErrors = document.querySelectorAll(".input.error").length > 0; if (hasErrors) { e.preventDefault(); // 有错误则阻止提交 } else { form.submit(); // 无错误则触发表单提交 } });
3. 修正拼写错误
将checkLenghth函数名改为规范的checkLength(不影响功能,但提升代码可读性):
// 检查输入长度 function checkLength(input, min, max) { if (input.value.length < min) { showError( input, `${getFieldName(input)} must be at least ${min} characters ` ); } else if (input.value.length > max) { showError( input, `${getFieldName(input)} must be less than ${max} characters ` ); } else { showSuccess(input); } }
完整修改后的代码
JavaScript 部分
const form = document.getElementById("form"); const P_FirstName = document.getElementById("P_FirstName"); const P_LastName = document.getElementById("P_LastName"); const P_Email = document.getElementById("P_Email"); const P_PhoneNum = document.getElementById("P_PhoneNum"); const ParentID = document.getElementById("ParentID"); const Password = document.getElementById("Password"); // 显示错误信息 function showError(input, message) { const formControl = input.parentElement; formControl.classList.remove("success"); formControl.classList.add("error"); const small = formControl.querySelector("small"); small.innerText = message; } // 显示成功状态 function showSuccess(input) { const formControl = input.parentElement; formControl.classList.remove("error"); formControl.classList.add("success"); } // 获取字段名称(首字母大写) function getFieldName(input) { return input.id.charAt(0).toUpperCase() + input.id.slice(1); } // 检查必填字段 function checkRequired(inputArr) { inputArr.forEach(function(input) { if (input.value.trim() === "") { showError(input, `الرجاء اكمال المعلومات`); } else { showSuccess(input); } }); } // 检查输入长度 function checkLength(input, min, max) { if (input.value.length < min) { showError( input, `${getFieldName(input)} must be at least ${min} characters ` ); } else if (input.value.length > max) { showError( input, `${getFieldName(input)} must be less than ${max} characters ` ); } else { showSuccess(input); } } // 检查名字格式(仅字母) function checkFirstName(input) { var letters = /^[A-Za-z]+$/; var ArabicLetters = /^([\u0600-\u06ff]|[\u0750-\u077f]|[\ufb50-\ufbc1]|[\ufbd3-\ufd3f]|[\ufd50-\ufd8f]|[\ufd92-\ufdc7]|[\ufe70-\ufefc]|[\ufdf0-\ufdfd])*$/g; if (input.value.match(letters) || input.value.match(ArabicLetters)) { showSuccess(input); } else { showError( input, `الاسم الاول يجب ان يتضمن حروف فقط بلا أرقام ` ); } } // 检查姓氏格式(仅字母) function checkLastName(input) { var letters = /^[A-Za-z]+$/; var ArabicLetters = /^([\u0600-\u06ff]|[\u0750-\u077f]|[\ufb50-\ufbc1]|[\ufbd3-\ufd3f]|[\ufd50-\ufd8f]|[\ufd92-\ufdc7]|[\ufe70-\ufefc]|[\ufdf0-\ufdfd])*$/g; if (input.value.match(letters) || input.value.match(ArabicLetters)) { showSuccess(input); } else { showError( input, `الاسم الاخير يجب ان يتضمن حروف فقط بلا أرقام ` ); } } // 检查邮箱格式 function checkEmail(input) { var validRegex = new RegExp(/^("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i); if (input.value.match(validRegex)) { showSuccess(input); } else { showError(input, "البريد الالكتروني المدخل غير صحيح"); } } // 检查手机号格式 function checkPhoneNumber(input) { var Ph_regex = new RegExp(/^(009665|9665|\+9665|05|5)(5|0|3|6|4|9|1|8|7)([0-9]{7})$/); if (input.value.match(Ph_regex)) { showSuccess(input); } else { showError(input, "رقم الهاتف المدخل غير صحيح"); } } // 检查用户名格式 function checkUserName(input) { var usernameRegex = /^[a-zA-Z0-9]+$/; if (input.value.match(usernameRegex)) { showSuccess(input); } else { showError(input, " اسم المستخدم المدخل غير صحيح"); } } // 检查密码格式 function checkPassword(input) { var passw = /^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{6,16}$/; if (input.value.match(passw)) { showSuccess(input); } else { showError(input, "يجب ان تحتوي كلمة المرور على احرف كبيرة وصغيرة ، ورقم و رمز واحد على الاقل"); } } // 表单提交事件 form.addEventListener("submit", (e) => { // 重置所有字段状态 const allInputs = [P_FirstName, P_LastName, P_Email, P_PhoneNum, ParentID, Password]; allInputs.forEach(input => { const formControl = input.parentElement; formControl.classList.remove("error", "success"); formControl.querySelector("small").innerText = ""; }); // 执行所有验证 checkRequired(allInputs); checkLength(Password, 8, 25); checkFirstName(P_FirstName); checkLastName(P_LastName); checkEmail(P_Email); checkPhoneNumber(P_PhoneNum); checkUserName(ParentID); checkPassword(Password); // 判断是否有错误 const hasErrors = document.querySelectorAll(".input.error").length > 0; if (hasErrors) { e.preventDefault(); } else { form.submit(); } });
HTML 部分(无需修改)
<div> <div class="con"> <h1> إنشاء حساب جديد</h1> <form action="" id="form" class="form"> <div class="input" style="display:flex; flex-direction: row; justify-content: center; align-items: center"> <label for="P_FirstName">الاسم الاول</label> <input type="text" name="P_FirstName" id="P_FirstName" autocomplete="off" /> <small>Error message</small> </div> <div class="input" style="display:flex; flex-direction: row; justify-content: center; align-items: center"> <label for="P_LastName">الاسم الاخير</label> <input type="text" name="P_LastName" id="P_LastName" autocomplete="off" /> <small>Error message</small> </div> <div class="input" style="display:flex; flex-direction: row; justify-content: center; align-items: center" lang="en"> <label for="P_Email">البريد الالكتروني</label> <input type="text" name="P_Email" id="P_Email" placeholder="user@gmail.com" autocomplete="off" /> <small>Error message</small> </div> <div class="input" lang="en" style="display:flex; flex-direction: row; justify-content: center; align-items: center"> <label for="P_PhoneNum">رقم الهاتف </label> <input type="text" name="P_PhoneNum" id="P_PhoneNum" placeholder="05xxxxxxxx" autocomplete="off" /> <small>Error message</small> </div> <div class="input" lang="en" style="display:flex; flex-direction: row; justify-content: center; align-items: center"> <label for="ParentID">اسم المستخدم </label> <input type="text" name="ParentID" id="ParentID" autocomplete="off" /> <small>Error message</small> </div> <div class="input" lang="en" style="display:flex; flex-direction: row; justify-content: center; align-items: center"> <label for="Password">كلمة المرور </label> <input type="password" name="Password" id="Password" placeholder="********" /> <small>Error message</small> </div> <button type="submit">إكمال</button> </form> </div> </div>
额外优化建议
可以给输入框添加实时验证事件,用户输入时即时反馈,提升体验:
// 示例:实时验证名字 P_FirstName.addEventListener("input", () => { if (P_FirstName.value.trim()) { checkFirstName(P_FirstName); } });
内容的提问来源于stack exchange,提问作者Hadeel
相关产品推荐
相关产品推荐

