JavaScript 表单验证
JavaScript 表单验证 (Form Validation) 深度指南表单验证是 Web 开发中至关重要的一环。它不仅能提升用户体验即时反馈还能减轻服务器压力但必须记住前端验证永远不能替代后端验证安全性。本指南将涵盖从 HTML5 原生验证到高级自定义验证的完整方案。一、验证的两大阵营1. HTML5 原生验证 (Constraint Validation API)利用浏览器内置能力无需写 JS 即可实现基础验证。优点代码少、性能好、自动支持无障碍 (A11y)、自动显示浏览器默认提示。缺点样式定制困难、逻辑复杂时难以维护、提示信息不够灵活。2. JavaScript 自定义验证完全由 JS 控制验证逻辑和 UI 反馈。优点逻辑灵活、UI 完全可控、可集成复杂规则如密码强度、实时比对。缺点代码量大、需处理浏览器兼容性、需手动处理无障碍。最佳实践混合使用。利用 HTML5 处理基础规则必填、格式利用 JS 处理复杂逻辑和自定义 UI。二、HTML5 原生验证 (Constraint Validation)1. 常用属性属性作用示例required必填项input requiredtype类型检查email,url,number,telpattern正则匹配input pattern[A-Za-z]{3}min/max数值/日期范围input typenumber min1 max100minlength/maxlength长度限制input minlength6step步长 (数字/日期)input typenumber step0.012. 核心 API (Constraint Validation API)属性/方法描述element.validity返回ValidityState对象包含详细状态element.validationMessage浏览器默认的报错信息element.checkValidity()返回true(有效) 或false(无效)element.reportValidity()触发浏览器默认提示 UI (气泡)element.setCustomValidity(msg)设置自定义错误(非空字符串即视为无效)3.ValidityState对象详解当validity.valid为false时可以通过以下属性判断具体原因属性含义触发条件valueMissing值缺失required且为空typeMismatch类型不匹配typeemail但格式不对tooShort/tooLong长度越界超出minlength/maxlengthrangeUnderflow低于最小值 minrangeOverflow高于最大值 maxpatternMismatch正则不匹配pattern不匹配stepMismatch步长不匹配step不匹配badInput输入无效用户输入了类型不允许的值 (如数字框输入字母)customError自定义错误调用了setCustomValidity(msg)4. 实战原生验证 自定义提示formidregFormdivclassform-grouplabel邮箱:/labelinputtypeemailidemailrequiredspanclasserror-msg/span/divdivclassform-grouplabel密码:/labelinputtypepasswordidpasswordminlength8requiredspanclasserror-msg/span/divbuttontypesubmit注册/button/formstyle.form-group{margin-bottom:15px;}.error-msg{color:red;font-size:12px;display:block;min-height:18px;}input:invalid:not(:placeholder-shown){border-color:red;}input:valid:not(:placeholder-shown){border-color:green;}/stylescriptconstformdocument.getElementById(regForm);constemaildocument.getElementById(email);constpassworddocument.getElementById(password);// 监听 input 事件实时验证[email,password].forEach(input{input.addEventListener(input,(){consterrorSpaninput.nextElementSibling;if(input.validity.valid){errorSpan.textContent;input.setCustomValidity();// 清除自定义错误}else{// 优先显示自定义错误否则显示默认错误if(input.validity.customError){errorSpan.textContentinput.validationMessage;}elseif(input.validity.valueMissing){errorSpan.textContent此项不能为空;}elseif(input.validity.typeMismatch){errorSpan.textContent请输入有效的邮箱地址;}elseif(input.validity.tooShort){errorSpan.textContent至少需要${input.minLength}个字符;}else{errorSpan.textContentinput.validationMessage;// 兜底}}});});// 提交处理form.addEventListener(submit,(e){e.preventDefault();// 触发所有验证并显示默认气泡 (可选)// form.reportValidity();if(form.checkValidity()){alert(验证通过提交数据);// form.submit();}else{// 手动触发所有字段的错误提示form.reportValidity();}});/script三、JavaScript 自定义验证 (高级场景)当 HTML5 无法满足需求时如密码强度、两次密码比对、动态规则使用 JS 完全控制。1. 验证规则设计模式建议将验证规则配置化便于维护。construles{email:{required:true,pattern:/^[^\s][^\s]\.[^\s]$/,messages:{required:邮箱不能为空,pattern:邮箱格式不正确}},password:{required:true,minLength:8,pattern:/^(?.*[a-z])(?.*[A-Z])(?.*\d).{8,}$/,// 必须包含大小写和数字messages:{required:密码不能为空,minLength:密码至少8位,pattern:密码必须包含大小写字母和数字}},confirmPassword:{required:true,equalTo:#password,// 自定义规则等于另一个字段messages:{required:请确认密码,equalTo:两次密码不一致}}};2. 通用验证函数functionvalidateField(field,rules){constvaluefield.value.trim();consterrorSpanfield.nextElementSibling;// 假设错误信息在下一个元素// 1. 必填检查if(rules.required!value){showError(field,errorSpan,rules.messages.required);returnfalse;}// 如果非必填且为空直接通过if(!value){clearError(field,errorSpan);returntrue;}// 2. 长度检查if(rules.minLengthvalue.lengthrules.minLength){showError(field,errorSpan,rules.messages.minLength);returnfalse;}// 3. 正则检查if(rules.pattern!rules.pattern.test(value)){showError(field,errorSpan,rules.messages.pattern);returnfalse;}// 4. 自定义规则 (如 equalTo)if(rules.equalTo){consttargetValuedocument.querySelector(rules.equalTo).value;if(value!targetValue){showError(field,errorSpan,rules.messages.equalTo);returnfalse;}}// 通过clearError(field,errorSpan);returntrue;}functionshowError(field,span,msg){field.style.borderColorred;span.textContentmsg;// 可选移除 setCustomValidity 避免冲突field.setCustomValidity(msg);}functionclearError(field,span){field.style.borderColor;span.textContent;field.setCustomValidity();}3. 集成到表单constformdocument.getElementById(regForm);constfields{email:document.getElementById(email),password:document.getElementById(password),confirmPassword:document.getElementById(confirmPassword)};// 实时验证Object.keys(fields).forEach(key{constfieldfields[key];field.addEventListener(blur,()validateField(field,rules[key]));field.addEventListener(input,(){// 输入时清除错误提升体验if(field.style.borderColorred){validateField(field,rules[key]);}});});// 提交验证form.addEventListener(submit,(e){e.preventDefault();letisValidtrue;Object.keys(fields).forEach(key{if(!validateField(fields[key],rules[key])){isValidfalse;}});if(isValid){alert(提交成功);// 发送 AJAX 请求}});四、常见验证场景代码片段1. 密码强度验证 (实时反馈)constpassworddocument.getElementById(password);conststrengthBardocument.getElementById(strengthBar);password.addEventListener(input,(){constvalpassword.value;letstrength0;if(val.length8)strength;if(/[a-z]/.test(val))strength;if(/[A-Z]/.test(val))strength;if(/\d/.test(val))strength;if(/[^a-zA-Z0-9]/.test(val))strength;// 更新 UIconstcolors[red,orange,yellow,lightgreen,green];constlabels[弱,较弱,中等,较强,强];strengthBar.style.width${(strength/5)*100}%;strengthBar.style.backgroundColorcolors[strength-1]||red;strengthBar.textContentlabels[strength-1]||;});2. 手机号验证 (中国大陆)functionvalidatePhone(phone){constregex/^1[3-9]\d{9}$/;returnregex.test(phone);}3. 身份证验证 (18位)functionvalidateIDCard(id){constregex/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;returnregex.test(id);}五、用户体验 (UX) 最佳实践实时反馈在blur(失去焦点) 时验证而不是submit时。在input时清除错误提示不要让用户一直看到红字。清晰的错误信息避免“输入错误”要说“邮箱格式不正确请包含 符号”。错误信息颜色使用红色位置在输入框下方。不要过度验证用户还没输完不要报错例如密码长度。避免在输入过程中频繁弹出浏览器默认气泡。无障碍 (A11y)使用aria-invalidtrue标记无效字段。使用aria-describedby关联错误信息让屏幕阅读器读取。inputidemailaria-invalidtruearia-describedbyemail-errorspanidemail-errorrolealert邮箱格式错误/span防止重复提交提交时禁用按钮防止用户多次点击。六、安全警告后端验证是必须的永远不要信任前端验证用户可以禁用 JavaScript。用户可以修改 HTML 属性。用户可以直接通过 API 发送请求。后端验证流程接收数据。再次执行所有验证规则长度、格式、业务逻辑。如果验证失败返回错误信息给前端。如果验证通过处理业务逻辑。七、常用验证库 (可选)如果项目复杂手写验证逻辑太繁琐可以使用成熟库VeeValidate(Vue 生态首选)Formik Yup(React 生态首选)jQuery Validate(老旧项目)Parsley.js(轻量级)八、总结场景推荐方案基础验证(必填、邮箱、数字)HTML5required,type,patternreportValidity()自定义错误提示setCustomValidity() 自定义 UI复杂逻辑(密码强度、比对)JavaScript 自定义验证函数实时反馈input/blur事件监听安全性必须在后端再次验证核心公式HTML5 基础规则 JS 自定义逻辑 实时 UX 反馈 后端安全验证 完美的表单验证